2012-04-07 132 views
3

我正在写一个聊天服务器,并在单元测试时遇到以下问题。在我的一个单元测试中,我将许多测试客户端连接到我的服务器。当连接的用户数达到511时,服务器停止响应而没有任何错误消息。在这个阶段,所有东西都在PC上本地运行。Twisted:到TCP服务器的客户端连接数有限?

我准备了一个简单的服务器,测试客户端和单元测试代码来粘贴到论坛中。

任何想法为什么服务器挂断? 任何帮助非常感谢

此代码基本上是从扭曲的简单聊天教程。 简单服务器:

from twisted.internet.protocol import Factory 
from twisted.protocols.basic import LineReceiver 
from twisted.internet import reactor 

class Chat(LineReceiver): 

    def __init__(self, users, userNum): 
     self.users = users 
     self.userNum = userNum 

    def connectionMade(self): 
     print "Connected to user %d" % (self.userNum) 
     self.users[self.userNum] = self 

    def connectionLost(self, reason): 
     print "Connection to user %d lost" % (self.userNum) 
     if self.users.has_key(self.userNum): 
      del self.users[self.userNum] 

    def lineReceived(self, line): 
     for user in self.users: 
      if user == self.userNum: 
       continue 
      self.users[user].sendLine("%d - %s" % (self.userNum, line)) 

class ChatFactory(Factory): 

    def __init__(self): 
     self.users = {} # maps user names to Chat instances 
     self.nUsers = 0 

    def buildProtocol(self, addr): 
     self.nUsers += 1 
     return Chat(self.users, self.nUsers) 

    def clientConnectionFailed(self, connector, reason): 
     print 'connection failed:', reason.getErrorMessage() 
     reactor.stop() 

    def clientConnectionLost(self, connector, reason): 
     print 'connection lost:', reason.getErrorMessage() 
     reactor.stop() 

reactor.listenTCP(8123, ChatFactory()) 
reactor.run() 

这是我的测试客户端。这个客户通过单元测试实例化几次。

import socket 

HOST = "localhost" 
PORT = 8123 

class TestClient: 
    def __init__(self): 
     self.connected = False 
     try: 
      self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     except socket.error, msg: 
      print("Socket error %s" % msg) 

    def connect(self): 
     try: 
      self.socket.settimeout(10) 
      self.socket.connect((HOST, PORT)) 
      self.connected = True 
     except socket.error, msg: 
      print("Socket error %s" % msg) 
      self.connected = False 

    def disconnect(self): 
     self.socket.close() 

    def connected(self): 
     return self.connected 

最后单元测试代码文件:

import unittest 
from TestClient import TestClient 

class TestSequenceFunctions(unittest.TestCase): 

    def test_manyUsers(self): 
     users = [] 

     number_of_users = 1000 

     for u in range(number_of_users): 
      # create client 
      users.append(TestClient()) 
      # connect client to server 
      users[-1].connect() 
      # check connected state 
      self.assertTrue(users[-1].connected, "User %d is not connected" % (u)) 

     # close connection of all users 
     for user in users: 
      user.disconnect() 

if __name__ == '__main__': 
    unittest.main() 
+0

这是什么操作系统?可能是你达到操作系统限制? – 2012-04-07 12:01:40

+0

感谢您的回答。我目前正在研究Windows 7 64位。我不确定服务器在什么操作系统上运行,什么时候联机。我怎样才能找出操作系统的限制(如果有的话)? – Zoli 2012-04-07 12:04:04

回答

4

数511是相当可疑。它足够接近2的强度,我的最初预感是任意强加的限制或错误。

既然你提到你在Windows上,我想我可以说这是一个任意强加的限制和一点信心。 select(2)支持的套接字数量在所有平台上都受到限制,但Windows上的限制甚至低于平时。默认情况下,它实际上是64.但是,Python将此限制提高到512(在大多数平台上限制不可变,但它在Windows上 - 编译时为C)。

失败后,511用户听起来像是如果这是你的系统的限制会发生什么 - 第512个插座是一个监听连接。

这样的大多数限制很难以一般的方式找到。通常你必须深入挖掘低层API或系统调用的使用情况,然后查看他们的文档,或者询问并希望其他(不幸)记住所有各种限制的人帮助你。 :)

您可以通过在Windows上使用基于IOCP的反应器来避免此限制。切换到非常容易。只需插入这些线路之前第一线在你的服务器:

from twisted.internet import iocpreactor 
iocpreactor.install() 

其他一切保持不变(和,特别是,现有的电抗器的进口保持不变,而你继续使用reactor,你不切换到您的程序中其他任何地方使用iocpreactor)。

您可以在Twisted的在线文档中阅读有关reactor selection的更多信息。

+0

非常感谢Jean-Paul,我会尽快测试iocpreactor并报告它。 – Zoli 2012-04-11 16:31:15

相关问题