我在這裏是一個noob,但試圖設置一個腳本,我可以輪詢一個套接字,並且當沒有套接字數據發送時,循環繼續運行並執行其他操作。我一直在玩使用select()發現的幾個例子,但不管我如何組織代碼,它似乎停止在server.recv()行上或附近,並等待響應。如果客戶端沒有發送數據,或者沒有客戶端連接,我想跳過這一點。Python套接字選擇正在掛起 - 在等待套接字數據時執行其他任務?
請注意,此應用程序不需要服務器腳本發送任何答覆數據,如果它有任何區別。
實際應用是運行一個循環併爲一些LED設置動畫(需要根訪問Raspberry Pi上的I/O)。我將通過套接字從另一個單獨的腳本發送此腳本數據,這些套接字將傳遞動畫的控制參數。這樣外部腳本不需要root權限。
到目前爲止,數據的發送和接收都非常有效,我無法在沒有輸入數據的情況下獲得循環。這是我的理解,這是select()打算允許的,但我發現的例子似乎並沒有這樣工作。
我試圖添加server.setblocking(0)幾個不同的地方無濟於事。 (如果我理解正確,一個非阻塞實例應該允許代碼跳過recv(),如果沒有數據已經發送,但我可能會關閉)。
我有我的基礎上這裏的示例代碼: http://ilab.cs.byu.edu/python/select/echoserver.html
這裏是服務器端腳本,然後客戶端腳本。
服務器代碼:sockselectserver.py
#!/usr/bin/env python
import select
import socket
import sys
server = socket.socket()
host = socket.gethostname()
port = 20568
size = 1024
server.bind((host,port))
server.listen(5)
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)
print "looping"
server.close()
客戶端代碼:skclient.py
#!/usr/bin/python # This is client.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 20568 # Reserve a port for your service.
s.connect((host, port))
data = "123:120:230:51:210:120:55:12:35:24"
s.send(data)
print s.recv(1024)
s.close # Close the socket when done
我想什麼通過這個例子來實現,就是看 「循環」 重複永遠,然後當客戶端腳本發送數據時,看到數據打印,然後一遍又一遍地看到「循環」恢復打印。那會告訴我它正在做我打算從那裏拿到的東西。
有趣的是,當我按照原樣進行測試時,無論何時運行客戶端,我都會在屏幕上看到「循環」打印3次,然後就不再顯示了。我不完全理解選擇內部發生了什麼,但我認爲它只會打印一次。
我試着將inputready .. select.select()移動到不同的地方,但發現它似乎需要每次調用,否則服務器停止響應(例如,如果它在無盡的while :循環)。
我希望這可以做得很簡單,它可以教授製造商類的其他黑客類型,所以我希望我不需要太多瘋狂的多線程和更復雜的解決方案。作爲最後的手段,我正考慮從外部腳本中將所有參數記錄到mySQL,然後使用此腳本將它們從表格中查詢回來。我有經驗,可能會工作,但似乎這個插座角度將是一個更直接的解決方案。
任何幫助,非常感謝。
服務器必須是它自己的循環imo – YOU
感謝您的快速回復。我不知道我將如何實現這一點。你能分享一個示例代碼片段嗎?我是否將所有內容都封裝在一個循環中?如果是,我會在哪裏調用其他函數(那些將被反覆調用的函數,僅在客戶端發送傳入數據時纔會中斷)? – kjav
嘗試使用超時(秒)調用'select.select()'選項:'select.select(input,[],[],1)'。 – acw1668