我正在使用Python編寫一個面向網絡的應用程序。我以前曾使用過阻塞套接字,但是在更好地理解了需求和概念之後,我想使用非阻塞套接字編寫應用程序,從而使用事件驅動的服務器。Python的select模塊中的select()函數如何正確工作?
我知道Python中select模塊中的函數可以用來方便地查看哪些套接字感興趣,等等。爲實現這一目標,我基本上是試圖通過幾個事件驅動服務器的例子,翻轉和我曾經碰到過這樣一句:
"""
An echo server that uses select to handle multiple clients at a time.
Entering any line of input at the terminal will exit the server.
"""
import select
import socket
import sys
host = ''
port = 50000
backlog = 5
size = 1024
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host,port))
server.listen(backlog)
input = [server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == server:
# handle the server socket
client, address = server.accept()
input.append(client)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
else:
# handle all other sockets
data = s.recv(size)
if data:
s.send(data)
else:
s.close()
input.remove(s)
server.close()
,我似乎沒有明白的部分如下:
在代碼片段inputready,outputready,exceptready = select.select(input,[],[])
中,我相信select()
函數返回三個可能爲空的輸入,輸出和異常條件對象的空列表。所以有意義的是select()
函數的第一個參數是包含服務器套接字和stdin的列表。但是,我所面臨的困惑是在else
代碼塊中。
由於我們正在循環使用已輸入套接字的列表,因此顯然select()
函數將選擇一個準備好讀取的客戶機套接字。但是,在我們使用recv()
讀取數據並發現套接字實際上已發送數據之後,我們希望將其回顯給客戶端。我的問題是我們如何寫入這個套接字而不將它添加到作爲select()
函數調用的第二個參數傳遞的列表中?也就是說,我們如何直接在新套接字上調用send()
,而不用將其註冊爲select()
作爲可寫套接字?
此外,爲什麼我們只能通過套接字準備好讀取(在這種情況下輸入已準備好)?是否有必要遍歷輸出結果列表以查看哪些套接字已準備好寫入? 顯然,我在這裏失去了一些東西。
如果有人能夠以更詳細的方式解釋功能的工作或指向良好的文檔,這也將非常有幫助。
謝謝。
我覺得你被樣本代碼的細節混淆。調用發送套接字而不等待它準備好寫入就沒有問題,但是如果輸出緩衝區已滿,就會阻塞。他們在示例代碼中忽略了這種情況。你可能想查看'select'手冊頁,因爲這是一個很薄的包裝器。我假設你已經找到http://docs.python.org/2/library/select.html –