2014-11-21 94 views
1

我已经使用SocketServer模块来创建一个小型服务器。它主要工作,但我有一个关于多个客户端同时accesing服务器的一些问题:Python socketserver - 与threading.Lock()交互?

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

  2. 我尝试添加ThreadingMixin。在这种情况下,我需要保护的服务器代码的某一代码块与锁

 
lock = threading.Lock() 
with lock: 
    # Do stuff here ... 
    # ... 

# Continue in unlocked scope. 

但锁好像忽略了 - 整个事情崩溃。而不是与我也尝试使用lock.aquire()& lock.release() - 那么它似乎无条件地封锁lock.aquire()。所以对我来说,似乎ThreadingMixin不会很好地与threading.Lock()一起玩。

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

class MyThreadedHandler(SocketServer.BaseRequestHandler): 

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

所以 - 我想每个线程将锁定它的个人锁 - 不是非常多一点!

+1

对于问题#2,您能向我们展示一个我们可以运行的小例子来证明您看到的问题吗?创建自己的锁定和锁定应该没有问题 - 不应该被忽略,也不应该让程序崩溃。 (通过崩溃,你的意思是有例外吗?)除非你正在做一些特殊的需要'acquire()'或'release()'的东西,否则坚持用'lock'。不要忘记锁定相同的锁(不是由同一行代码创建的两个或多个不同的锁!) – 2014-11-21 16:35:53

回答

1
  1. 当您在BaseServer上致电serve_forever时,该线程专用于处理服务器的事件。传入连接和数据在套接字队列中等待,直到线程有空闲时抓取它们。因此,新的连接和数据将一直等到您的当前处理程序返回。如果你有一个处理程序阻塞,所有传入的连接和数据将一直等到它完成。

您可以等待的连接数量有一个适度的限制。一旦超过这个限制,TCP协议栈通常会发送一个RESET来告诉另一端消失。您可以通过覆盖server_activate并调用具有较大值听更改值:

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

谦虚不一定是坏事 - 它让你的服务器不被淹没。

套接字将会排队的数据量也有限制,但它对它更加温和。它只是通知对方,它的接收窗口已满,请稍后闭嘴。

编辑 2.与锁的问题....锁应该与资源(通常是数据,但也许一个I/O端口,甚至写一个文件关联,以确保线路别交叉)需要保护,而不是线程正在执行。如果你有多个锁,你必须小心......死锁很容易写!

+0

非常感谢;在这种情况下,我已经用Python自己编写了这个小而简单的客户端。 TCP RESET是否会被操作系统透明地处理,还是我不得不在客户端手动支持的东西? – user422005 2014-11-21 17:32:39

+0

@ user422005 - 由操作系统自动完成。 – tdelaney 2014-11-21 17:39:16

0

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

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

如果您的ServerSocket没有并行处理连接(与线程或进程),则并发连接必须等待。如果有太多的并发连接,看起来它们会被丢弃。