我需要服务器向所有客户端(Python、套接字)发送消息
这是我的服务器程序,它如何将从每个客户端接收到的数据发送到其他客户端我需要服务器向所有客户端(Python、套接字)发送消息,python,multithreading,sockets,networking,tcp,Python,Multithreading,Sockets,Networking,Tcp,这是我的服务器程序,它如何将从每个客户端接收到的数据发送到其他客户端 import socket import os from threading import Thread import thread def listener(client, address): print "Accepted connection from: ", address while True: data = client.recv(1024) if not dat
import socket
import os
from threading import Thread
import thread
def listener(client, address):
print "Accepted connection from: ", address
while True:
data = client.recv(1024)
if not data:
break
else:
print repr(data)
client.send(data)
client.close()
host = socket.gethostname()
port = 10016
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(3)
th = []
while True:
print "Server is listening for connections..."
client, address = s.accept()
th.append(Thread(target=listener, args = (client,address)).start())
s.close()
如果需要向所有客户端发送消息,则需要以某种方式保留所有客户端的集合。例如:
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()
将部分内容分解成单独的函数可能会更清楚,例如执行所有发送的广播函数
无论如何,这是最简单的方法,但也有问题:
- 如果一个客户端的连接速度很慢,那么其他所有人都可能会陷入对它的写操作。当他们在轮到他们写的时候,他们没有读任何东西,所以你可能会溢出缓冲区,开始断开所有人的连接
- 如果一个客户端出现错误,其线程正在写入该客户端的客户端可能会出现异常,这意味着您最终将断开与错误用户的连接
因此,更好的解决方案是为每个客户机提供一个队列,以及一个为该队列提供服务的writer线程和reader线程。(然后,您可以通过各种方式扩展此功能,对队列进行限制,以便人们不再试图与远远落后的人交谈,等等)
正如所指出的,除了每个客户机使用一个(或两个)线程外,还有一种不同的服务器设计方法:使用多路复用所有客户机事件的线程
Python3.x为此内置了一些很棒的库,但2.7只有笨重的、过时的/和低级的
正如Anzel所说,他有一个使用asyncore
的答案,值得一读。但我不会用这个。如果您想用Python2.x编写一个基于reactor的服务器,我要么使用更好的第三方框架,比如,或者找到或编写一个非常简单的框架,直接放在select
上,不要试图将Python代码作为可运行的代码片段发布;这只适用于JS/HTML/CSS。(这次我编辑了它。)作为旁注,您的代码混合了制表符和空格。这真是个坏主意;这很容易导致Python无法像您或其他人那样理解块结构。你应该考虑切换到一个帮助你避免这个问题的编辑器,也可以用“代码> Python T-T/<代码>或<代码> Python TT < /Cube >运行脚本,以验证你已经修复了它,并且没有重新创建它。请看看这个被接受的答案,也许这正是你正在寻找的,特别是@abarnert的所有建议都在一个小的实现示例中得到了解决。@Anzel:我个人不建议使用asyncore
,但这个答案仍然值得一看。(而且,由于评论偶尔会被删除,我将信息复制到了我的答案中。)@abarnert,你能再详细说明一下你为什么反对使用asyncore
?要向客户发送多条信息,我确实认为这是一个不错的选择,因此我想从您的角度了解更多信息,准确解决OP将面临的问题。感谢您提供的详细答案!