简体   繁体   English

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

[英]python socket server/client protocol with unstable client connection

I have a threaded python socket server that opens a new thread for each connection. 我有一个线程python套接字服务器,为每个连接打开一个新线程。

The thread is a very simple communication based on question and answer. 该线程是基于问答的非常简单的通信。 Basically client sends initial data transmission, server takes it run an external app that does stuff to the transmission and returns a reply that the server will send back and the loop will begin again until client disconnects. 基本上客户端发送初始数据传输,服务器将其运行一个外部应用程序,对传输执行操作并返回服务器将发回的回复,并且循环将再次开始,直到客户端断开连接。

Now because the client will be on a mobile phone thus an unstable connection I get left with open threads no longer connected and because the loop starts with recv it is rather difficult to break on lost connectivity this way. 现在因为客户端将在移动电话上,因此连接不稳定,我不再连接开放线程,并且因为循环以recv开始,所以很难以这种方式打破丢失的连接。

I was thinking on adding a send before the recv to test if connection is still alive but this might not help at all if the client disconnects after my failsafe send as the client sends a data stream every 5 seconds only. 我正在考虑在recv之前添加一个send来测试连接是否仍处于活动状态但是如果客户端在我的故障安全发送后断开连接,这可能没有任何帮助,因为客户端仅每5秒发送一次数据流。

I noticed the recv will break sometimes but not always and in those cases I am left with zombie threads using resources. 我注意到recv有时会破坏但并非总是如此,在这种情况下,我会使用资源留给僵尸线程。

Also this could be a solid vulnerability for my system to be DOSed. 这也可能是我的系统被DOS操作的一个可靠漏洞。 I have looked through the python manual and Googled since thursday trying to find something for this but most things I find are related to client and non blocking mode. 我已经浏览了python手册和Google搜索,因为我周四试图找到一些东西,但我找到的大多数东西都与客户端和非阻塞模式有关。

Can anyone point me in the right direction towards a good way on fixing this issue? 任何人都可以指出我正确的方向,以解决这个问题吗?

Code samples: 代码示例:

Listener: 监听器:

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()

Handler: 处理器:

  # 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()

As you can see there are three conditions that at least one should trigger exit if connection fails but sometimes they do not. 如您所见,有三个条件,如果连接失败,至少有一个条件应该触发退出,但有时它们不会。

Sorry, but I think that threaded idea in this case is not good. 对不起,但我认为在这种情况下, threaded想法并不好。 As you do not need to process/do a lot of stuff in these threads (workers?) and most of the time these threads are waiting for socket (is the blocking operation, isn't it?) I would advice to read about event-driven programming . 因为你不需要在这些线程中处理/执行很多东西(工作者?),并且大多数时候这些线程都在等待socket(是阻塞操作,不是吗?)我建议阅读有关事件的信息驱动编程 According to sockets this pattern is extremly useful, becouse you can do all stuff in one thread. 根据套接字,这种模式非常有用,因为你可以在一个线程中完成所有工作。 You are communicate with one socket at a time, but the rest of connections are just waiting to data so there is almost no loss. 您一次与一个套接字进行通信,但其余连接只是等待数据,因此几乎没有丢失。 When you send several bytes you just check that maybe another connection requires carrying. 当您发送几个字节时,您只需检查可能需要携带另一个连接。 You can read about select and epoll . 你可以阅读有关选择epoll的信息

In python there is several libraries to play with this nicly: 在python中有几个库可以使用这个:

I used tornado in some projects and it is done this task very good. 我在一些项目中使用龙卷风,这项任务非常好。 Libev is nice also, but is a c-wrapper so it is a little bit low-level (but very nice for some tasks). Libev也很好,但它是一个c-wrapper所以它有点low-level (但对于某些任务非常好)。

So you should use socket.settimeout(float) with the clientsocket like one of the comments suggested. 所以,你应该使用socket.settimeout(float)clientsocket类似意见的一个建议。

The reason you don't see any difference is, when you call socket.recv(bufsize[, flags]) and the timeout runs out an socket.timeout exception is thrown and you catch that exception and exit. 您没有看到任何区别的原因是,当您调用socket.recv(bufsize[, flags])并且超时耗尽时,抛出socket.timeout异常并捕获该异常并退出。

try:
      data = clientsocket.recv(1)
except:
      sys.exit()

should be somthing like: 应该是这样的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM