2012-04-07 174 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

相關問題