我要瘋了在python中編寫一個小套接字服務器。一切工作正常,但我注意到,在客戶端剛剛消失的情況下,服務器無法辨別。我通過拉動客戶端和服務器之間的以太網電纜來模擬這一點,關閉客戶端,然後重新插入電纜。服務器從不會聽到客戶端斷開連接,並且將永遠等待,從不允許更多客戶端連接。Python套接字客戶端消失,服務器不能告知
我想我會通過給讀取循環添加一個超時來解決這個問題,以便它每隔10秒嘗試讀取一次。我想也許如果它試圖從套接字讀取它會注意到客戶端丟失。但後來我意識到服務器確實無法知道這一點。
所以我添加了心跳。如果服務器在未讀取的情況下進入10秒鐘,則會將數據發送到客戶端。然而,即使這是成功的(意味着不會拋出任何異常)。所以我能夠讀取和寫入一個不存在的客戶端。有沒有什麼方法可以知道客戶端沒有在客戶端和服務器之間實現某種挑戰/響應協議而走了?這將是一個突破性的變化,我想避免它。
這裏是我的代碼爲這個核心:
def _loop(self):
command = ""
while True:
socket, address = self._listen_socket.accept()
self._socket = socket
self._socket.settimeout(10)
socket.sendall("Welcome\r\n\r\n")
while True:
try:
data = socket.recv(1)
except timeout: # Went 10 seconds without data
pass
except Exception as e: # Likely the client closed the connection
break
if data:
command = command + data
if data == "\n" or data == "\r":
if len(command.strip()) > 0:
self._parse_command(command.strip(), socket)
command = ""
if data == '\x08':
command = command[:-2]
else: # Timeout on read
try:
self._socket.sendall("event,heartbeat\r\n") # Send heartbeat
except:
self._socket.close()
break
心跳的sendall不會拋出一個異常,recv的唯一拋出超時(或其他異常,如果客戶能夠正確地關閉下正常連接情況)。
任何想法?我錯了,發送給一個沒有ACK的客戶端最終會產生一個異常(我測試了幾分鐘)。
它應該失敗........最終...當系統合理確信沒有可行路線存在。由於可行的鏈路可能涉及撥號調制解調器或信鴿等缺陷,這可能需要很長時間。如您所懷疑的那樣,應用程序級輪詢/確認通常用於在「安靜」間隔期間監視可達性,而不會在對等端之間交換其他數據。 –
另外'服務器從不會聽到客戶端斷開連接,並且將永遠等待,永遠不會允許更多的客戶端連接。' - 指出您的服務器設計存在嚴重問題。一個卡住/ AWOL客戶端不應該阻止他人連接/通信! –