我正在编写聊天服务器,并在进行单元测试时遇到以下问题。在我的一个单元测试中,我将许多测试客户端连接到我的服务器。当连接用户数达到511时,服务器停止响应而没有任何错误消息。在这个阶段,一切都在PC上本地运行。
我准备了一个简单的服务器,测试客户端和单元测试代码以粘贴到论坛中。
知道服务器挂机的原因吗? 非常感谢任何帮助
这段代码基本上来自扭曲的简单聊天教程。 简单的服务器:
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 :(得分:4)
号码511相当可疑。它足够接近2的幂,我最初的预感是任意施加的限制或错误。
既然你提到你在Windows上,我想我可以说这是一个任意强加的限制,有点自信。 select(2)支持的套接字数量在所有平台上都受到限制,但在Windows上限制甚至低于平常。默认情况下,它实际上是64.但是,Python将此限制提升到512(这个限制在大多数平台上都不可变,但它在Windows上 - 在 C 编译时)。
失败的511用户听起来如果这是你的系统的限制会发生什么 - 第512个套接字是监听连接的那个。
这样的大多数限制很难以一般方式找到。通常,您必须深入了解正在使用的低级API或系统调用,然后查找他们的文档,或者询问并希望有(不幸)记住所有各种限制的其他人帮助您。 :)
您可以在Windows上使用基于IOCP的reactor来避免此限制。切换到很容易。只需在服务器中的第一行之前插入行
from twisted.internet import iocpreactor
iocpreactor.install()
其他所有内容保持不变(特别是,您现有的reactor导入保持不变,并且继续使用reactor
,您不会切换到在程序中的任何其他地方使用iocpreactor
)
您可以在Twisted的在线文档中阅读有关reactor selection的更多信息。