協程:gevent模塊,遇到i/o自動切換任務 038

協程 : gevent模塊,遇到io自動切換任務算法

from gevent import monkey;monkey.patch_all()  # 寫在最上面 這樣後面的全部阻塞就所有可以識別了
import gevent  # 直接導入便可
from threading import current_thread
import time
def eat(name):
    print('%seat1'% name)
    # gevent.sleep(2)
    time.sleep(2)   # 加上monkey就能
    print('%seat2'% name)
    print(current_thread().getName())
def play(name):
    print('%splay1'% name)
    # gevent.sleep(2)
    time.sleep(2)
    print('%splay2'% name)
    print(current_thread().getName())
g1 = gevent.spawn(eat,'egon')  # 建立一個協程對象 spawn括號內第一個參數是函數名
g2 = gevent.spawn(play,'egon')
gevent.joinall([g1,g2]) # 將g1.join()和g2.join()合成一步寫了出來
print('')
# 結果爲
# egoneat1
# egonplay1
# egoneat2
# DummyThread-1  # 假線程 虛擬線程 其實都在一個線程裏面 
# egonplay2
# DummyThread-2
#

    gevent.sleep(2)模擬的是gevent能夠識別的io阻塞,服務器

    而 time.sleep(2)或其餘阻塞 是不能直接識別的 須要用下面一行代碼打補丁 就能夠識別了網絡

    from gevent import monkey;monkey.patch_all() 放在time, socket以前 或者直接將其放在文件開頭.架構

    協程是經過本身的程序實現切換 本身可以控制 只有遇到協程模塊可以識別io操做的時候, 程序纔會進行任務切換 實現併發效果 , 若是全部的程序都沒有io操做 那麼久基本屬於串行執行了.併發

給你們看一個線程下(協程)來實現多個客戶聊天app

io多路複用:模型(解決問題方案)socket

#服務端
from socket import *
import select
server  = socket(AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8093))
server.listen(5)
# 設置爲非阻塞
server.setblocking(False)
# 將初始化服務端socket對象加入監聽列表 後面還要動態添加一些conn鏈接對象, 當accept的時候sk就有感應 , 當recv的時候conn就有動靜
rlist = [server,]
rdata = {}  # 存放客戶端發送過來的消息
wlist = []  # 等待寫對象
wdata = {}  # 存放要返回客戶端的消息
print('準備監聽!')
count = 0 # 寫着計數用的 爲了看實驗效果用的 , 沒用
while 1:
    # 開始select監聽,對rlist中服務端server進行監聽 , select函數阻塞進程 , 直到rlist中套接字被觸發(在此例中,套接字接收到客戶端發來的握手信號 , 從而變得可讀 知足select函數的可讀條件),被觸發的(有動靜的)套接字(服務器套接字)返回給了rl這個返回值裏面;
    rl,wl,xl = select.select(rlist,wlist,[],0.5)
    print('%s 次數>>'%(count),wl)
    count = count + 1
    # 對rl進行循環判斷是否有客戶端鏈接進來 , 當有客戶端鏈接進來時select將觸發
    for sock in rl:
        # 判斷當前觸發的是否是socket對象, 當觸發的對象是socket對象時說明有新客戶端accept鏈接進來了
        if sock == server:
            # 接收客戶端的鏈接, 獲取客戶端對象和客戶端地址信息
            conn,addr = sock.accept()
            # 把新的客戶端鏈接加入到監聽列表中 當客戶端鏈接有接受消息的時候 , select將會被觸發 ,會知道這個連接有動靜 , 有消息 , 那麼返回geirl這個返回值列表裏面
            rlist.append(conn)
        else:
            # 因爲客戶端鏈接進來時socket接收客戶端請求 , 將客戶端鏈接加入到了監聽列表中(rlist),客戶端發送消息的時候這個連接將觸發
            # 因此判斷是不是客戶端鏈接對象觸發
            try:
                data = sock.recv(1024)
                # 沒有數據的時候,將這個鏈接關閉掉 , 並從監聽列表中移除
                if not data:
                    sock.close()
                    rlist.remove(sock)
                    continue
                print('received{0} from client{1}'.format(data.decode(),sock))
                # 將接收到的客戶端的消息保存下來
                rdata[sock] = data.decode()
                # 將客戶端鏈接對象和這個對象接受到的消息加工成返回消息 , 並添加到wdata這個字典裏面
                wdata[sock] = data.upper()
                # 要給這個客戶端回覆消息的時候, 咱們將這個連接添加到wlist監聽列表中
                wlist.append(sock)
            # 若是這個鏈接出錯了,客戶端暴力斷開了(注意 , 尚未接收到客戶端的消息 , 或者接收消息的過程當中出錯了)
            except Exception:
                # 關閉這個鏈接
                sock.close()
                # 在監聽列表中將他刪除 , 由於無論什麼緣由 畢竟是斷開了 不必再監聽他了
                rlist.remove(sock)
    # 若是如今沒有客戶端請求鏈接 也沒有客戶端發送消息時 , 開始對發送消息的列表進行處理 , 是否須要發送消息
    for sock in wl:
        sock.send(wdata[sock])
        wlist.remove(sock)
        wdata.pop(sock)
    # 將以此select監聽列表中有接收數據的conn對象所接收到的消息打印一下
    # for k , v in rdata.items():
    #       print(k,'發來的消息是',v)
    # # 清空接收到的消息
    #rdata.clear()
View Code

  知識總結 : tcp

    1 cs架構 bs架構ide

    2 網絡通訊流程:函數

       網卡 mac地址 子網掩碼 網關 dns服務器 dhcp nat(網絡地址轉換)  端口(表示電腦上某個應用程序)  路由器 交換機 集線器 廣播 單播 廣播風暴 ARP協議 路由協議

    3 網絡網絡通訊協議(**)

      osi七層 應表會傳網數物

      tcp\ip協議  應用層 網絡層 數據鏈路層 物理層

      tcp(*****)

        三次握手 客-->服--->客

        四次揮手 

        tcp和udp區別(*****)

          tcp: 面向鏈接 消息可靠 效率相對差 面向流的消息格式 無消息保護邊界

          udp:面向無鏈接 不可靠 效率很高 面向包的消息格式 有消息保護邊界

    4 socket

        緩衝區:

        粘包現象 : 1 連續發送小包而且間隔時間很短 就會發送兩個消息合併在一塊兒的狀況 (Nagel優化算法致使的)  2 一次發送數據過大 對方一次未接收完 下次接受的時候連同第一次剩下的消息一同接受了 致使粘包

        解決粘包方案 都不知道對方發送的消息長度   1 發送消息以前先發送消息長度 收到對方確認信息後再次發送消息  2 經過struct 模塊 自定義報頭 將消息長度打包成4個字節長度的信息 連同你要發送的數據一併發過去

        打包 pack('i',長度)   長度是個整數       

相關文章
相關標籤/搜索