1. 程式人生 > >並發編程網絡編程和數據庫的基礎操作

並發編程網絡編程和數據庫的基礎操作

同步阻塞 存取 p地址 thread item 本質 8.0 proc 針對

第二部分

網絡編程之 osi七層模型和三次握手四次揮手 socket

# by luffycity.com
# 概念
    # 應用層 http https ssl smtp ftp
    # 傳輸層 tcp udp  端口信息  四層路由器 四層交換機
        # tcp
            # 可靠的 面向連接的 全雙工的 流式傳輸 效率低
            # 三次握手和四次揮手
                # 三次握手
                    # 把圖背下來 syn ack
                # 四次揮手
                    # 把圖背下來 fin ack
            # 黏包 : (自定義協議)先發送數據的長度,再發送數據
        # udp 效率高 不可靠 無連接 基於數據包的傳輸 能夠傳輸的數據的長度有限
    # 網絡層     ipv4協議192.168.0.1    ipv6協議 ff2312:f5242:12:1:1:1   網關地址 子網掩碼 路由器 三層交換機
    # 數據鏈路層 mac地址 arp(通過ip地址找mac地址),rarp(通過mac地址找ip地址) 網卡  交換機
    # 物理層


# 1.評論  限制長度   數據庫的carchar(255)
# 2.即時聊天的工具   udp

# socket
# socketserver

# 手寫socket
# server - tcp
import socket
# sk = socket.socket()
# sk.bind(('127.0.0.1',9000))
# sk.listen()
#
# # while True表示能夠和多個client通信
# conn,addr = sk.accept()  # 建立三次握手的過程
# # while True表示能夠和一個client說多句話
# conn.recv(1024)
# conn.send(b'xxx')
# conn.close()
# sk.close()  # 四次揮手中的兩手

# client -tcp
# import socket
# sk = socket.socket()
# sk.connect(('127.0.0.1',9000))
#
# sk.send(b'hello')
# sk.recv(1024)
# sk.close()   # 四次揮手中的兩手

# server -udp
# import socket
# sk = socket.socket(type=socket.SOCK_DGRAM)
# sk.bind(('127.0.0.1',9000))
# while True:
#     msg,cli_addr = sk.recvfrom(1024)
#     sk.sendto(msg,cli_addr)
# sk.close()

# clients -udp
import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.sendto(b'msg',('127.0.0.1',9000))
msg,_ = sk.recvfrom(1024)
print(msg)
sk.close()



並發編程

# by luffycity.com
# 操作系統
# 異步同步\阻塞非阻塞\並發並行
# 並發和並行
    # 並行 能利用多核 同一時刻 有多個任務在CPU上同時執行
    # 並發 不能利用多核 同一時間段內 有多個任務在一個CPU上輪流被執行
    # 並行 : 多進程 多線程(在其他語言中)
# 同步和異步
    # 同步 當我執行一個任務  需要等待這個任務的結果才能繼續執行下一個任務
    # 異步 當我執行某一個任務 不需要等待這個任務的結果 就可以繼續執行下一個任務
# 阻塞和非阻塞
    # 非阻塞 : cpu一直在工作
    # 阻塞 : CPU不工作 recv recvfrom accept input sleep
# io操作(輸入輸出都是針對內存的,str,bytes)
    # input : input read recv recvfrom accept connet close
    # output: write send sendto connet accept close

# 同步阻塞
# def func():
#     import time
#     time.sleep(1)
#
# def func2():
#     func()
#     print(123)
# func2()

# 同步非阻塞
# def func():
#     a = 1
#     b= a+1
#     return b
# def func2():
#     func()
#     print(123)
# func2()

# 異步阻塞
# import time
# import threading
# def func():
#     time.sleep(1)
# t_l = []
# for i in range(10):
#     t = threading.Thread(target=func)
#     t.start()
#     t_l.append(t)
# for t in t_l:t.join()

# 異步非阻塞
# 我調用一個函數 不等待這個函數的結果
# 並且我能一直利用cpu

# 在正常的編程語言中
# 進程 是計算機中最小資源分配單位
    # 數據隔離 開銷(開啟 銷毀 切換)大 內存級別數據安全 但是文件操作\數據庫操作數據不安全
    # manager : 數據共享
    # IPC(inter process communication):隊列\消息隊列memcache\rabbitmq\redis
        # 管道 : 基於socket + pickle
        # 原生的queue : 基於文件(管道 + 鎖)
        # 第三方工具 : 基於網絡\穩定性更強
# 線程 計算機中能被CPU調度的最小單位
    # 數據共享 開銷(開啟 銷毀 切換)小 數據不安全 數據共享程序可能會同時去操作一個變量
# 協程 本質是一條線程 協程任務對於操作系統來說不可見 協程是用戶級的單位
    # 數據共享 開銷非常小(函數的調用的速度一樣快) 數據絕對安全
# 在Cpython解釋器下
    # 進程
    # 線程 不能利用多核 (flask django) : 文件操作更快
        # GIL鎖 : 全局解釋器鎖,鎖的是線程,保證了同一個進程中的多個線程之間只有一個線程能訪問CPU
                 # 限制了一個python進程中的多線程不能利用多核
        # 無法處理高計算型的任務
            # 解決方案 開多進程
    # 協程(tonado tiwsted sanic scrapy) : 所有的time.sleep socket 協程更快
        # 一條線程
        # 指的是程序能夠在多個協程任務之間來回切換
        # 如果在程序中遇到io就切換去執行另一個程序,實現了使用協程來規避io,提高cpu的使用率
# def func():
#     yield 1
#     print(123)
#     yield 2
# def func2():
#     g = func()
#     g.__next__()
        # asyncio 基於yield關鍵字\gevent 基於greenlet來完成的
        # aiohttp

# 操作系統中的IO多路復用
# select poll epoll
# select windows
# poll epoll linux
# epoll最好

# 代理,監聽所有的網絡對象,是否有讀\寫事件發生
# import socket
# import select
# sk = socket.socket()
# sk.setblocking(False)
# sk.bind(('127.0.0.1',9000))
# sk.listen()
# read_l = [sk]
# while True:
#     rl,wl,el = select.select(read_l,[],[])   # 阻塞
#     for item in rl:
#         if item is sk:
#             conn,addr = sk.accept()
#             read_l.append(conn)
#         else:
#             msg = item.recv(1024)
#             if msg == b'':
#                 read_l.remove(item)
#                 continue
#             print(msg)
#             item.send(b'received')
# io多路復用
    # 代理所有的網絡對象,幫助我們監聽有哪一個對象發生了註冊事件(讀\寫\異常),然後通知程序,去進行相應的處理

# selectors模塊
# 能夠有效的利用poll和epoll前提是你所在的操作系統是有這兩個機制的
# 自動的識別當前操作系統中我們能用的最好的機制
#服務端
from socket import *
import selectors

sel=selectors.DefaultSelector()
def accept(sk,mask):
    conn,addr=sk.accept()
    sel.register(conn,selectors.EVENT_READ,read)

def read(conn,mask):
    try:
        data=conn.recv(1024)
        if not data:
            print('closing',conn)
            sel.unregister(conn)
            conn.close()
            return
        conn.send(data.upper()+b'_SB')
    except Exception:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sk=socket(AF_INET,SOCK_STREAM)
sk.bind(('127.0.0.1',8088))
sk.listen(5)
sk.setblocking(False)

sel.register(sk,selectors.EVENT_READ,accept) #相當於網select的讀列表裏append了一個文件句柄server_fileobj,並且綁定了一個回調函數accept

while True:
    events=sel.select() # 代理在這裏等待,等events事件來,一旦等來了 那麽一定是有新的鏈接 來 或者是有發送給conn的數據來
    for sel_obj,mask in events:
        callback=sel_obj.data #callback=accpet/read
        callback(sel_obj.fileobj,mask) #accpet(server_fileobj,1)

# select 只能使用select
# selector 能用select poll epoll
# select 采用輪詢,能夠處理的對象的個數有限
# poll 采用輪詢,能夠處理的對象的個數無限的
# epoll 回調

# TCP協議
# 監聽多個sk,conn對象,誰的數據先來,我就通知誰來處理
# 好處是什麽
    # 把很個等待變成一個等待,有一個代理替我們來接收所有的請求


# 1.刷一下考試題
    # 把所有課上沒有講過答案的 圈出來

數據庫1

# by luffycity.com
# 非關系型數據庫
# mongdb 智能玩具
# redis  路飛項目
# kafka 消息中間件

# 關系型數據庫
# oracle
# sqllite

# mysql
# ddl dml dcl
# 版本的數據庫 5.6/ 5.7 / 8.0
# 存儲引擎
    # innodb 5.6版本以上默認的存儲引擎
        # 支持事務
            # select + update
            # begin;
            # select * from 表 where 條件 for update;
            # update 表 set 字段=值 where 條件;
            # commit;
        # 行級鎖 :
            # 對於少量數據的並發的修改效率更高
            # 但是對於整個表中大量字段的修改鎖反而拖慢了速度
        # 支持外鍵
        #     create table 表名(
        #     字段名 數據類型(長度) 約束,
        #     uid int,
        #     foreign key uid references user(ui)
        #     on update cascade
        #     )
    # myisam 5.5版本以下默認的存儲引擎
        # 查詢速度和insert的速度都很快
        # 表級鎖 : 對高並發的大量修改沒有優勢的
        # innodb支持的都不支持
    # memory
        # 斷電消失
    # blakhole
        # 多級主從復制 往裏寫啥啥沒
        # binary_log = bin_log
        # sql -> 分析 -> 優化 -> 編譯 -> 二進制的操作


數據庫2

# by luffycity.com
# 數據類型
    # 數字
        # in
        # float
    # 字符串
        # char(4)    定長:存取快 浪費空間 提倡
        # varchar(4) 變長:存取慢 節省空間
    # 時間
        # 內置函數 :now year month day
        # datetime
        # timestamp
        # year date time
    # 枚舉和集合
        # enum 枚舉單選
        # create table t(gender enum('male','female'))
        # set  集合多選去重
        # create table t(hobby set('抽煙','喝酒'))
# 約束條件
    # 非空 not null
    # 默認值 default
    # 唯一  unique
        # 聯合唯一 unique(字段1,字段2)   # 姓和名  # ip和端口
        # 唯一+int 自增 auto_increment
    # 主鍵 primary key (非空+唯一)
        # 聯合主鍵 primary key(字段1,字段2)
    # 外鍵 foreign key

# 表結構操作
    # 創建表結構   *****
    # 刪除表結構
        # drop table 表名;
    # 修改表結構
        # alter table 表名 add 字段 數據類型 約束信息 first
        # alter table 表名 add 字段 數據類型 約束信息 after 某字段
        # alter table 表名 modify 修改數據的數據類型和約束條件
        # alter table 表名 modify 已經存在的字段名 新的類型 新的約束 first
        # alter table 表名 change 已經存在的字段名 新字段名 新的類型 新的約束 first
        # alter table 表名 drop 字段/索引
    # 查看表結構   *****
        # desc 表名;
        # show create table 表名;



數據庫3

# by luffycity.com
# 記錄操作 dml
    # 增
        # insert into 表 (字段) values (值1,值2,),(值1,值2,),(值1,值2,);
    # 刪
        # delete from table where 條件
        # delete from table;刪除整個表中的數據 ,自增字段的offset還在
    # 改
        # update 表 set 字段=值,字段2=值2 where 條件
    # 查
        # 單表
            # select id from 表
                    # where 條件
                    # group by 字段  是可以使用別名的
                    # having 過濾條件 只能查select字段中或者group by 或者使用了過濾條件
                    # order by 排序  asc desc
                    # limit m,n 從m+1開始,取n條
            # having
                # select name from 表 having age>20  # 報錯
                # select name from 表 group by age having avg(age)>20  # 正確
                # select name from 表 having avg(age)>20  # 正確
                # select name,age from 表 having age>20  # 正確

        # 多表
            # 連表查詢
            # 子查詢

client

# by luffycity.com
# import socket
#
# sk = socket.socket()
# sk.connect(('127.0.0.1',9000))
# while True:
#     sk.send(b'hello')
#     print(sk.recv(1024))
# sk.close()

#客戶端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8088))

while True:
    msg=input('>>: ')
    if not msg:continue
    c.send(msg.encode('utf-8'))
    data=c.recv(1024)
    print(data.decode('utf-8'))

並發編程網絡編程和數據庫的基礎操作