【问题标题】:Twisted: number of client connections to TCP server limited?Twisted:与 TCP 服务器的客户端连接数受限?
【发布时间】:2012-04-07 11:47:13
【问题描述】:

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

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

知道为什么服务器挂了? 非常感谢任何帮助

这段代码基本上来自于twisted simple chat tutorial。 简单服务器:

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

【问题讨论】:

  • 这是什么操作系统?会不会是你达到了操作系统限制?
  • 感谢您的回答。我目前正在使用 Windows 7 64 位。我不确定服务器将在什么操作系统上运行,当它上线时。如何找出操作系统的限制(如果有的话?)

标签: twisted tcpserver


【解决方案1】:

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 的更多信息。

【讨论】:

  • 非常感谢 Jean-Paul,我会测试 iocpreactor 并在收到后立即报告。
猜你喜欢
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 2016-10-05
  • 2022-01-16
相关资源
最近更新 更多