2012-04-07 14 views
3

Ich schreibe einen Chat-Server und habe beim Testen des Geräts das folgende Problem festgestellt. In einem meiner Komponententests verbinde ich viele Testclients mit meinem Server. Wenn die Anzahl der verbundenen Benutzer 511 erreicht, reagiert der Server nicht mehr ohne Fehlermeldung. Zu diesem Zeitpunkt läuft alles lokal auf einem PC.Twisted: Anzahl der Client-Verbindungen zu TCP-Server begrenzt?

Ich habe einen einfachen Server vorbereitet, Test-Client und Unit-Test-Code zum Einfügen in das Forum.

Irgendeine Idee, warum der Server aufhängt? Jede Hilfe wird sehr geschätzt

Dieser Code ist grundlegend von der verdrehten einfachen Chat-Tutorial. Einfacher Server:

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

Dies ist mein Test-Client. Dieser Client wird durch den Komponententest mehrmals instanziiert.

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 

Schließlich wird die Unit-Test-Code-Datei:

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

Welches Betriebssystem ist das? könnte es sein, dass du das OS-Limit erreicht hast? –

+0

Danke für die Antwort. Ich arbeite derzeit an Windows 7 64 Bit. Ich bin mir nicht sicher, auf welchem ​​OS der Server läuft, wenn er online geht. Wie kann ich die Begrenzung des Betriebssystems herausfinden (wenn es eines gibt?) – Zoli

Antwort

4

Die Zahl 511 ist ziemlich verdächtig. Es liegt nahe genug an einer Zweierpotenz, dass meine anfängliche Ahnung ein willkürlich festgelegtes Limit oder ein Fehler ist.

Da Sie erwähnt haben, dass Sie auf Windows sind, kann ich sagen, dass es sich um ein willkürlich festgelegtes Limit mit ein wenig Selbstvertrauen handelt. Die Anzahl der Sockets, die von select (2) unterstützt werden, ist auf allen Plattformen begrenzt, aber das Limit ist noch niedriger als unter Windows üblich. Standardmäßig ist es tatsächlich 64. Allerdings erhöht Python dieses Limit auf 512 (das Limit ist auf den meisten Plattformen nicht veränderbar, aber es ist unter Windows - unter C Kompilierzeit).

Failing nach 511 Benutzer klingt nur, was passieren würde, wenn dies das Limit für Ihr System wäre - der 512. Socket ist derjenige, der auf Verbindungen wartet.

Die meisten dieser Grenzen sind im Allgemeinen schwer zu finden. Normalerweise müssen Sie herausfinden, welche Low-Level-API oder Systemaufrufe verwendet werden, und dann ihre Dokumentation nachschlagen oder fragen und hoffen, dass jemand anderes, der sich (leider) alle verschiedenen Grenzen auswendig gelernt hat, Ihnen hilft. :)

Sie können dieses Limit vermeiden, indem Sie den IOCP-basierten Reaktor unter Windows verwenden. Es ist sehr einfach zu wechseln. Legen Sie einfach diese Zeilen vor die ersten Zeilen in Ihrem Server:

from twisted.internet import iocpreactor 
iocpreactor.install() 

Alles andere gleich bleibt (und insbesondere Ihrer bestehenden Reaktor Import bleibt gleich, und Sie halten reactor verwenden, nicht wahr wechseln Sie zur Verwendung von iocpreactor irgendwo anders in Ihrem Programm).

Sie können mehr über reactor selection in Twisted Online-Dokumentation lesen.

+0

Vielen Dank Jean-Paul, ich werde iocpreactor testen und darüber berichten, sobald ich dazu komme. – Zoli

Verwandte Themen