Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
客户端连接不稳定的python套接字服务器/客户端协议_Python_Sockets - Fatal编程技术网

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

客户端连接不稳定的python套接字服务器/客户端协议,python,sockets,Python,Sockets,我有一个线程化的python套接字服务器,它为每个连接打开一个新线程 线程是基于问答的非常简单的通信。 基本上,客户端发送初始数据传输,服务器让它运行一个外部应用程序,该应用程序对传输进行处理,并返回服务器将发送回的回复,循环将再次开始,直到客户端断开连接 现在,由于客户端将在移动电话上,因此连接不稳定,我留下的开放线程不再连接,并且由于循环从recv开始,因此很难通过这种方式中断失去的连接 我正在考虑在recv之前添加一个发送,以测试连接是否仍然处于活动状态,但如果客户端在我的故障保护发送后断

我有一个线程化的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()

正如您所见,如果连接失败,至少有一种情况会触发退出,但有时不会。

因此您应该使用
socket.settimeout(float)
clientsocket
一起使用

您看不到任何差异的原因是,当您调用
socket.recv(bufsize[,flags])
时,超时将超出
socket。超时将引发异常,您捕获该异常并退出

try:
      data = clientsocket.recv(1)
except:
      sys.exit()
应该是这样的:

try:
      data = clientsocket.recv(1)
except timeout:
      #timeout occurred
      #handle it
      clientsocket.close()
      sys.exit()

对不起,但我认为在这种情况下,
线程化
的想法是不好的。由于您不需要在这些线程中处理/做很多事情(worker?),而且这些线程大部分时间都在等待套接字(是阻塞操作,不是吗?),我建议您阅读一下。根据sockets的说法,这种模式非常有用,因为你可以在一个线程中完成所有的事情。您一次只能与一个套接字通信,但其余的连接只是等待数据,因此几乎没有丢失。当您发送几个字节时,您只需检查是否需要另一个连接。你可以读到 和

在python中,有几个库可用于此功能:

  • libev(c库包装器)-

我在一些项目中使用了tornado,它很好地完成了这项任务。Libev也很不错,但它是一个c-wrapper,所以它有点
低级
(但对于某些任务来说非常好)。

你能发布代码的相关部分吗?您正在使用Queue.Queue吗?通过使用Queue.Queue,您可以查看是否有作业在等待线程,然后可以设置线程超时,如果线程没有得到任何东西,则可以完成。我没有使用twisted或其他任何东西。我想到了两件事-你可以尝试套接字对象的.timeout()函数,在套接字()上不活动几秒钟后关闭clientsocket()。或者我还认为,稍微重写程序的多线程部分以使用队列。使用队列的好处是设置要允许的线程数以及处理传递给这些线程的作业。我最近才发现,它让我大吃一惊。serversocket.settimeout(10)使服务器断开连接,而clientsocket.settimeout(10)似乎不起作用。过了一段时间(有时几个小时,有时几天——我想这取决于客户端在失去连接时停止通信的方式和时间)。@tntu:你还在寻求帮助解决这个问题吗?如果是这样,您能否确保上面的代码是最新的,并运行linux命令
ss-taeon
,发布标题行和挂起连接的一行。这将有助于了解网络级别上发生的情况。我的问题是脚本实际上没有超时,并且退出服务器脚本或客户端脚本在超时时没有运行哪个脚本?从python文档中可以看出:由于exit()最终“仅”引发异常,因此它只有在从主线程调用时才会退出进程,异常不会被截获。在一个线程中,线程将退出线程,与return相同,但我会接受您的想法并使用它,但这只是一个次要问题,不是我的主要问题。处理程序有时不会超时。这是相当困难的复制,因为它发生在一个非常不可预测的方式,即使客户端应用程序是相同的唯一区别是它安装在不同的手机上,但我没有注意到一个特定的手机,导致它实际上我需要线程。我有大量的同时连接,他们不能排队等候。它们需要立即处理。速度是关键。正如我提到的,客户是移动电话,而且有很多。如果他们不得不排队等待,最终大多数人都会在轮到他们之前超时。请阅读并查看该问题的解决方法(以及查看线程/工作者体系结构与IO任务中事件驱动的基准测试)。您可以看到,在这种情况下,工人模型不是一种“快速”方式。所以,如果你不做计算,我建议使用这种方法。好吧,就是这样。有大量的计算查询、外部应用程序调用等。