客户端连接不稳定的python套接字服务器/客户端协议



我有一个带线程的python套接字服务器,它为每个连接打开一个新线程。

线程是一种基于问答的非常简单的通信。基本上,客户端发送初始数据传输,服务器让它运行一个外部应用程序,该应用程序对传输进行处理,并返回服务器将发送回的回复,循环将再次开始,直到客户端断开连接。

现在,由于客户端将在手机上,因此连接不稳定,我留下的开放线程不再连接,并且由于循环从recv开始,因此很难以这种方式中断丢失的连接。

我曾考虑在recv之前添加一个发送,以测试连接是否仍然有效,但如果客户端在我的故障保护发送后断开连接,这可能根本没有帮助,因为客户端仅每5秒发送一个数据流。

我注意到recv有时会中断,但并不总是如此,在这些情况下,我只能使用僵尸线程使用资源。

此外,这可能是一个坚实的漏洞,我的系统被剂量。自周四以来,我一直在浏览python手册并在谷歌上搜索,试图找到一些相关内容,但我发现的大多数内容都与客户端和非阻塞模式有关。

有人能为我指出解决这个问题的正确方向吗?

代码示例:

监听器:

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在这种情况下的想法不好。由于你不需要在这些线程(worker?)中处理/做很多事情,而且大多数时候这些线程都在等待套接字(这是阻塞操作,不是吗?)我建议你阅读有关事件驱动编程的知识。根据套接字,这种模式非常有用,因为你可以在一个线程中完成所有的事情。您一次使用一个套接字进行通信,但其他连接只是在等待数据,因此几乎没有丢失。当你发送几个字节时,你只需要检查是否有其他连接需要携带。您可以阅读关于select和epoll。

在python中,有几个库可以用来nicly:

  • libev(c库包装器)-pyev
  • 龙卷风
  • 扭曲的

我在一些项目中使用了龙卷风,它做得很好。Libev也很好,但它是一个c包装器,所以它有点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()

相关内容

最新更新