Python socketserver - 与threading.Lock()的交互?

时间:2014-11-21 15:21:56

标签: python multithreading sockets

我使用SocketServer模块创建了一个小型服务器。它基本上有效,但我有一些关于多个客户端同时访问服务器的问题:

  1. 当使用绝对基本的TCP SocketServer时,即没有ThreadingMixin或ForkingMixin时 - 当第二个客户端在完成为第一个客户端提供服务之前尝试连接到服务器时会发生什么情况;将删除第二个连接 - 或者第二个客户端是否会被阻止?

  2. 我尝试过添加ThreadingMixin。在这种情况下,我需要使用锁

  3. 来保护服务器代码中的某个代码块
    lock = threading.Lock()
    with lock:
       # Do stuff here ...
       # ...
    
    # Continue in unlocked scope.
    

    但锁似乎被忽略了 - 整个事情都崩溃了。而不是我已经尝试过使用lock.aquire()& lock.release() - 然后似乎无条件地阻塞lock.aquire()。所以对我而言,ThreadingMixin似乎与threading.Lock()没有很好的协作?

    编辑:Dan关于使用相同锁定的评论可能是我锁定问题的关键;我当前的处理程序代码如下所示:

    class MyThreadedHandler(SocketServer.BaseRequestHandler):
    
       def handle(self):
          lock = threading.Lock()     <-- Each thread a separate lock?!
          with lock:
              # Do serial stuff
          # Continue parallell processing.
    

    所以 - 我想每个线程都会锁定它的个人锁定 - 不是很重要!

2 个答案:

答案 0 :(得分:1)

  1. 当您在serve_forever上呼叫BaseServer时,该线程专门用于处理服务器的事件。传入的连接和数据在套接字队列中等待,直到线程有空闲时间来获取它们。因此,新连接和数据将一直等到当前处理程序返回。如果您有一个阻止的处理程序,则所有传入的连接和数据将一直等到它完成。
  2. 您可以拥有待处理的连接数有一个适度的限制。一旦超过该限制,TCP堆栈通常会发送RESET以告知对方消失。您可以通过覆盖server_activate并使用更大的值调用listen来更改值:

    def server_activate(self):
        socket.listen(32)
    

    谦虚不一定是坏事 - 它可以防止服务器不堪重负。

    套接字将排队的数据量也有限制,但它对此更为温和。它只是告诉对方它的接收窗口是满的,请它闭嘴一段时间。

    修改的 2. lock .... lock的问题应该与资源相关联(通常是数据但可能是I / O端口,甚至是对文件的写入以确保线路不交错)需要保护,而不是执行的线程。如果你有多个锁,你必须要小心......死锁很容易写!

答案 1 :(得分:0)

要回答问题#1,当您同步使用服务器(绑定和侦听)套接字并且没有线程或分叉时,新连接将排队。他们等到服务器到处理它们。

在套接字上调用listen()时,参数是等待accept()被调用的连接队列的长度,它会逐个返回它们。

如果您的ServerSocket并非处理并行连接(使用线程或进程),则并发连接必须等待。如果并发连接太多,则会显示它们将被删除。