python庫之selectors

  在以前的博客中已經總結過度別在windows和linux操做系統下實現socket高併發(I/O異步)的方法,能夠參考基於epoll的TP傳輸層實現Windows之IOCPhtml

  下面對Python中實現socket高併發的selectors庫進行總結,官方參考文檔:https://docs.python.org/3/library/selectors.html python

1. 示例代碼

import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
    conn, addr = sock.accept()  # Should be ready
    print('accepted', conn, 'from', addr)
    conn.setblocking(False)
    sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
    data = conn.recv(1000)  # Should be ready
    if data:
        print('echoing', repr(data), 'to', conn)
        conn.send(data)  # Hope it won't block
    else:
        print('closing', conn)
        sel.unregister(conn)
        conn.close()

sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)

   上面示例代碼來自官方文檔,接下來對關鍵代碼進行重點說明linux

2. 重點知識說明

(1)conn.setblocking(False)windows

  設置socket的阻塞或非阻塞模式併發

  阻塞模式下當試圖對該文件描述符進行讀寫時,若是當時沒有東西可讀,或者暫時不可寫,程序就進入等待狀態,直到有東西可讀或者可寫爲止異步

  非阻塞模式下若是沒有東西可讀,或者不可寫,讀寫函數立刻返回,而不會等待socket

(2)sel.register(conn, selectors.EVENT_READ, read)函數

  對描述符進行註冊,也就是對該描述符的EVENT_READ事件進行監聽,當又READ事件通知時,調用回調函數read高併發

  selectors庫提供了兩個監聽事件:EVENT_READ和EVENT_WRITEpost

(3)sel.unregister(conn)

  註銷描述符

(4)events = sel.select()

  函數原型爲:abstractmethod select(timeout=None)

  該函數是實現I/O異步的關鍵,等待,直到一些已註冊的文件對象準備就緒,或者超時。

  若是timeout>0,則指定最大等待時間,以秒爲單位,若是超時沒有,則調用將阻塞,直到被監視的文件對象準備就緒。若是timeout< 0,調用將不會阻塞,並將報告當前就緒的文件對象。

  該函數返回一個元組(key, events)

  key爲class selectors.SelectorKey對象,SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])

  fileobj爲註冊的文件對象

  fd爲文件描述符

  data爲與文件對象相關聯的自定義數據,如上面的回調函數

  明確上面的4個知識點後會以爲selectors庫的使用很簡單

  最後對DefaultSelector進行說明,DefaultSelector會根據當前操做系統類型本身選擇selector類型

if 'KqueueSelector' in globals():
    DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
    DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
    DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
    DefaultSelector = PollSelector
else:
    DefaultSelector = SelectSelector
相關文章
相關標籤/搜索