2012-04-07 3 views
3

Я пишу чат-сервер и столкнулся со следующей проблемой во время тестирования модуля. В одном из моих модульных тестов я подключаю множество тестовых клиентов к моему серверу. По мере того, как количество подключенных пользователей достигает 511, сервер перестает отвечать без сообщения об ошибке. На этом этапе все работает локально на ПК.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

какая ОС это? может быть, вы попали в пределы ОС? –

+0

Спасибо за ответ. В настоящее время я работаю над Windows 7 64 бит. Я не уверен, на какой ОС будет работать сервер, когда он выйдет в Интернет. Как я могу узнать об ограничении ОС (если есть?) – Zoli

ответ

4

Число 511 является довольно подозрительно. Это достаточно близко к силе двух, что моя первоначальная догадка - произвольно установленный предел или ошибка.

Поскольку вы упомянули, что находитесь в Windows, я думаю, что могу сказать, что это произвольно установленный предел с некоторой долей уверенности. Количество сокетов, поддерживаемых select (2), ограничено на всех платформах, но в Windows этот предел даже ниже обычного. По умолчанию это на самом деле 64. Однако Python увеличивает это ограничение до 512 (предел не изменяется на большинстве платформ, но он находится в Windows - на C времени компиляции).

Неудача после 511 пользователей звучит как только то, что произойдет, если это будет ограничение в вашей системе - 512-й сокет - тот, кто слушает подключения.

Большинство ограничений, подобных этому, трудно найти в общем виде. Обычно вам приходится разбираться в том, какие низкоуровневые API-интерфейсы или системные вызовы используются, а затем просматривать их документацию или спрашивать и надеяться, что кто-то еще, кто (к сожалению) запомнил все различные ограничения, поможет вам. :)

Вы можете избежать этого ограничения, используя реактор на основе IOCP в Windows. Его очень легко переключить. Просто вставьте эти строки перед первые строки на сервере:

from twisted.internet import iocpreactor 
iocpreactor.install() 

Все остальное остается неизменным (и, в частности, существующий импорт реактор остается тем же самым, и продолжать использовать reactor, вы не переключитесь на использование iocpreactor в любом месте в вашей программе).

Вы можете узнать больше о reactor selection в онлайн-документации Twisted.

+0

Большое спасибо Жан-Поль, я буду тестировать iocpreactor и сообщать об этом, как только я доберусь до него. – Zoli