我檢查了stackoverflow.com上的幾個類似線程,我想我可能需要爲我的服務器腳本打開非阻塞套接字。因爲,我不確定這是否是問題標題可能是錯誤的解決方案。讓我解釋我的問題。服務器的非阻塞套接字
服務器應用程序等待連接,一旦客戶端連接,它會詢問服務器ID,然後客戶端將詢問服務器配置,然後客戶端將命令發送到服務器以開始測量傳輸。這裏是我的代碼的簡化版本:
def conn_handler(self, connection, address):
self.logger.info("[%d] - Connection from %s:%d", 10, address[0], address[1])
sending_measurements_enabled = False
try:
while True:
data = connection.recv(2048)
if data:
command = get_command_from_data(data)
else:
command = None
if command == 'start':
sending_measurements_enabled = True
elif command == 'stop':
break
elif command == 'id':
connection.sendall(self.id)
elif command == 'cfg':
connection.sendall(self.cfg)
if sending_measurements_enabled:
connection.sendall(measurement)
except Exception as e:
print(e)
finally:
connection.close()
print("Connection closed")
這裏是客戶端腳本:
try:
sock.sendall(get_id_command)
data = sock.recv(2048) # Do I need to wait for response?
print(data)
sock.sendall(get_conf_command)
data = sock.recv(2048)
print(data)
sock.sendall(start_sending_measurements)
data = sock.recv(2048)
print(data)
while True:
sock.sendall(bytes('I do not want this', 'utf-8')) # I would like to keep receiving measurements without this
data = sock.recv(2048)
print(data)
finally:
print('Closing socket...')
sock.close()
這裏是我的問題:
當我運行客戶端和發送命令,獲取ID服務器會返回ID消息,然後客戶端將發送命令獲取配置,服務器將返回配置消息,但當我發送start
命令服務器將發送只有一個測量,我猜connection.recv(2048)
將阻止執行,直到服務器獲得另一個comman d。所以,我在while True:
循環中添加了這行代碼,它將繼續發送(不必要的,無效的)命令,服務器將繼續發送測量結果。
如何解決這個問題,而不需要一直從客戶端發送命令。我希望只能發送一個命令start
,服務器將繼續發送測量結果,並且僅在客戶端發送stop
命令時停止。 此外,如果服務器在發送測量結果時收到id
或cfg
命令,它將首先發送id
或cfg
並繼續發送測量結果。
的'else'爲'如果數據:'應該像命令「停止」,因爲空'data'在這一點意味着對方已經關閉了連接因此不再發送任何東西。 – BlackJack
您也可以使用線程發送測量值,而不是非阻塞套接字。 – BlackJack
@BlackJack僅當客戶端試圖終止連接時才發送空包。如果客戶端沒有發送任何東西(在下面的代碼中)'如果可讀:'塊內的代碼永遠不會被執行,如果客戶端發送空包,這意味着連接應該被關閉? – sstevan