我要疯了在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客户端不应该阻止他人连接/通信! –