#呼叫 select 函式,阻塞等待
readable, writeable, exceptional =select.select(inputs, , )
#資料抵達,迴圈
for sock in
readable:
#監聽到有新的連線
if sock ==server:
conn, addr =server.accept()
#select 監聽的socket
#監聽到鍵盤有輸入
elif sock ==sys.stdin:
cmd =sys.stdin.readline()
running =false
break
#有資料到達
else
:
#讀取客戶端連線傳送的資料
data = sock.recv(1024)
ifdata:
sock.send(data)
else
:
#移除select監聽的socket
inputs.remove(sock)
sock.close()
#如果檢測到使用者輸入敲擊鍵盤,那麼就退出
select目前幾乎在所有的平台上支援,其良好跨平台支援也是它的乙個優點。
select的乙個缺點在於單個程序能夠監視的檔案描述符的數量存在最大限制,在linux上一般為1024,可以通過修改巨集定義甚至重新編譯核心的方式提公升這一限制,但是這樣也會造成效率的降低。
一般來說這個數目和系統記憶體關係很大,具體數目可以cat /proc/sys/fs/file-max察看。32位機預設是1024個。64位機預設是2048.
對socket進行掃瞄時是依次掃瞄的,即採用輪詢的方法,效率較低。
當套接字比較多的時候,每次select()都要通過遍歷fd_setsize個socket來完成排程,不管哪個socket是活躍的,都遍歷一遍。這會浪費很多cpu時間。
沒有最大併發連線的限制,能開啟的fd(指的是檔案描述符,通俗的理解就是套接字對應的數字編號)的上限遠大於1024
效率提公升,不是輪詢的方式,不會隨著fd數目的增加效率下降。只有活躍可用的fd才會呼叫callback函式;即epoll最大的優點就在於它只管你「活躍」的連線,而跟連線總數無關,因此在實際的網路環境中,epoll的效率就會遠遠高於select和poll。
#建立套接字
s =socket.socket(socket.af_inet,socket.sock_stream)
#設定可以重複使用繫結的資訊
s.setsockopt(socket.sol_socket,socket.so_reuseaddr,1)
#繫結本機資訊
s.bind(("",7788))
#變為被動
s.listen(10)
#建立乙個epoll物件
epoll=select.epoll()
#測試,用來列印套接字對應的檔案描述符
#print s.fileno()
#print select.epollin|select.epollet
#註冊事件到epoll中
#epoll.register(fd[, eventmask])
#注意,如果fd已經註冊過,則會發生異常
#將建立的套接字新增到epoll的事件監聽中
epoll.register(s.fileno(),select.epollin|select.epollet)
connections ={}
addresses ={}
#迴圈等待客戶端的到來或者對方傳送資料
while
true:
#epoll 進行 fd 掃瞄的地方 -- 未指定超時時間則為阻塞等待
epoll_list=epoll.poll()
#對事件進行判斷
for fd,events in
epoll_list:
#print fd
#print events
#如果是socket建立的套接字被啟用
if fd ==s.fileno():
conn,addr=s.accept()
print('
有新的客戶端到來%s
'%str(addr))
#將 conn 和 addr 資訊分別儲存起來
connections[conn.fileno()] =conn
addresses[conn.fileno()] =addr
#向 epoll 中註冊 連線 socket 的 可讀 事件
epoll.register(conn.fileno(), select.epollin |select.epollet)
elif events ==select.epollin:
#從啟用 fd 上接收
recvdata = connections[fd].recv(1024)
if len(recvdata)>0:
print('
recv:%s
'%recvdata)
else
:
#從 epoll 中移除該 連線 fd
epoll.unregister(fd)
#server 側主動關閉該 連線 fd
I O多路復用
一 五種i o模型 1 阻塞i o模型 最流行的i o模型是阻塞i o模型,預設情形下,所有套介面都是阻塞的。我們以資料報套介面為例來講解此模型 我們使用udp而不是tcp作為例子的原因在於就udp而言,資料準備好讀取的概念比較簡單 要麼整個資料報已經收到,要麼還沒有。然而對於tcp來說,諸如套介面...
i o多路復用
最常見的i o多路復用就是 select poll epoll了,下面說說他們的一些特點和區別吧。select 可讀 可寫 異常三種檔案描述符集的申明和初始化。fd set readfds,writefds,exceptionfds fd zero readfds fd zero writefds ...
I O多路復用
我們都知道unix like 世界裡,一切皆檔案,而檔案是什麼呢?檔案就是一串二進位製流而已,不管socket,還是fifo 管道 終端,對我們來說,一切都是檔案,一切都是流。在資訊 交換的過程中,我們都是對這些流進行資料的收發操作,簡稱為i o操作 input and output 往流中讀出資料...