如果您需要向所有客户端发送消息,则需要以某种方式保留所有客户端的集合。例如:
clients = set()
clients_lock = threading.Lock()
def listener(client, address):
print "Accepted connection from: ", address
with clients_lock:
clients.add(client)
try:
while True:
data = client.recv(1024)
if not data:
break
else:
print repr(data)
with clients_lock:
for c in clients:
c.sendall(data)
finally:
with clients_lock:
clients.remove(client)
client.close()
将其中的一部分分解为单独的函数可能会更清楚,例如broadcast
完成所有发送的函数。
无论如何,这就是simplest方法可以做到,但是有问题:
- 如果一个客户端的连接速度很慢,其他人都可能会陷入写入该客户端的困境。当他们轮到写入时发生阻塞时,他们不会读取任何内容,因此您可能会溢出缓冲区并开始断开每个人的连接。
- 如果一个客户端出现错误,则其线程正在写入该客户端的客户端可能会收到异常,这意味着您最终将断开错误的用户连接。
因此,更好的解决方案是为每个客户端提供一个队列,并在读取线程旁边提供一个为该队列提供服务的写入线程。 (然后,您可以通过各种方式扩展此功能 - 对队列进行限制,以便人们不再尝试与落后太多的人交谈,等等。)
As Anzel https://stackoverflow.com/users/3849456/anzel指出,有一个不同的除了每个客户端使用一个(或两个)线程之外设计服务器的方法:使用reactor http://en.wikipedia.org/wiki/Reactor_pattern多路复用所有客户端的事件。
Python 3.x 有一些很棒的内置库,但 2.7 只有笨重和过时的库asyncore https://docs.python.org/2/library/asyncore.html/asynchat https://docs.python.org/2/library/asynchat.html和低级select https://docs.python.org/2/library/select.html.
正如安泽尔所说,Python SocketServer:发送到多个客户端 https://stackoverflow.com/questions/3670127/python-socketserver-sending-to-multiple-clients有一个答案使用asyncore
,值得一读。但我实际上不会使用它。如果你想用 Python 2.x 编写一个基于 Reactor 的服务器,我要么使用更好的第三方框架,比如Twisted https://twistedmatrix.com/trac/,或者找到或写一个非常简单的直接位于select
.