[英]python socket server/client protocol with unstable client connection
我有一個線程python套接字服務器,為每個連接打開一個新線程。
該線程是基於問答的非常簡單的通信。 基本上客戶端發送初始數據傳輸,服務器將其運行一個外部應用程序,對傳輸執行操作並返回服務器將發回的回復,並且循環將再次開始,直到客戶端斷開連接。
現在因為客戶端將在移動電話上,因此連接不穩定,我不再連接開放線程,並且因為循環以recv開始,所以很難以這種方式打破丟失的連接。
我正在考慮在recv之前添加一個send來測試連接是否仍處於活動狀態但是如果客戶端在我的故障安全發送后斷開連接,這可能沒有任何幫助,因為客戶端僅每5秒發送一次數據流。
我注意到recv有時會破壞但並非總是如此,在這種情況下,我會使用資源留給僵屍線程。
這也可能是我的系統被DOS操作的一個可靠漏洞。 我已經瀏覽了python手冊和Google搜索,因為我周四試圖找到一些東西,但我找到的大多數東西都與客戶端和非阻塞模式有關。
任何人都可以指出我正確的方向,以解決這個問題嗎?
代碼示例:
監聽器:
serversocket = socket(AF_INET, SOCK_STREAM)
serversocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
serversocket.bind(addr)
serversocket.listen(2)
logg("Binded to port: " + str(port))
# Listening Loop
while 1:
clientsocket, clientaddr = serversocket.accept()
threading.Thread(target=handler, args=(clientsocket, clientaddr,port,)).start()
# This is useless as it will never get here
serversocket.close()
處理器:
# Socket connection handler (Threaded)
def handler(clientsocket, clientaddr, port):
clientsocket.settimeout(15)
# Loop till client closes connection or connection drops
while 1:
stream = ''
while 1:
ending = stream[-6:] # get stream ending
if ending == '.$$$$.':
break
try:
data = clientsocket.recv(1)
except:
sys.exit()
if not data:
sys.exit()
# this is the usual point where thread is closed when a client closes connection normally
stream += data
# Clear the line ending
stream = base64.b64encode(stream[:-6])
# Send data to be processed
re = getreply(stream)
# Send response to client
try:
clientsocket.send(re + str('.$$$$.'))
except:
sys.exit()
如您所見,有三個條件,如果連接失敗,至少有一個條件應該觸發退出,但有時它們不會。
對不起,但我認為在這種情況下, threaded
想法並不好。 因為你不需要在這些線程中處理/執行很多東西(工作者?),並且大多數時候這些線程都在等待socket(是阻塞操作,不是嗎?)我建議閱讀有關事件的信息驅動編程 。 根據套接字,這種模式非常有用,因為你可以在一個線程中完成所有工作。 您一次與一個套接字進行通信,但其余連接只是等待數據,因此幾乎沒有丟失。 當您發送幾個字節時,您只需檢查可能需要攜帶另一個連接。 你可以閱讀有關選擇和epoll的信息 。
在python中有幾個庫可以使用這個:
我在一些項目中使用龍卷風,這項任務非常好。 Libev也很好,但它是一個c-wrapper所以它有點low-level
(但對於某些任務非常好)。
所以,你應該使用socket.settimeout(float)
與clientsocket
類似意見的一個建議。
您沒有看到任何區別的原因是,當您調用socket.recv(bufsize[, flags])
並且超時耗盡時,拋出socket.timeout
異常並捕獲該異常並退出。
try:
data = clientsocket.recv(1)
except:
sys.exit()
應該是這樣的:
try:
data = clientsocket.recv(1)
except timeout:
#timeout occurred
#handle it
clientsocket.close()
sys.exit()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.