这是我的服务器程序,它如何将从每个客户端收到的数据发送给每个其他客户端?
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()
abarnert.. 10
如果需要向所有客户端发送消息,则需要以某种方式保留所有客户端的集合.例如:
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
所有发送的函数.
无论如何,这是最简单的方法,但它有问题:
如果一个客户端的连接速度很慢,那么其他所有人都可能会陷入困境.虽然他们轮流阻止写入,但他们没有阅读任何东西,所以你可以溢出缓冲区并开始断开所有人的连接.
如果一个客户端有错误,其线程正在写入该客户端的客户端可能会获得异常,这意味着您将最终断开错误的用户.
因此,更好的解决方案是为每个客户端提供队列,并为读取器线程提供服务该队列的编写器线程.(然后你可以通过各种方式扩展它 - 对队列设置限制,以便人们不再试图与远远落后的人交谈,等等)
正如Anzel所指出的,除了每个客户端使用一个(或两个)线程之外,还有一种不同的设计服务器的方法:使用多路复用所有客户端事件的反应器.
Python 3.x有一些很好的内置库,但2.7只有笨重和过时asyncore
/ asynchat
低级别select
.
正如Anzel所说,Python SocketServer:发送给多个客户端有一个答案asyncore
,值得一读.但我实际上不会使用它.如果你想在Python 2.x中编写一个基于反应器的服务器,我要么使用更好的第三方框架,比如Twisted,要么找到或写一个直接位于其上的非常简单的框架select
.
如果需要向所有客户端发送消息,则需要以某种方式保留所有客户端的集合.例如:
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
所有发送的函数.
无论如何,这是最简单的方法,但它有问题:
如果一个客户端的连接速度很慢,那么其他所有人都可能会陷入困境.虽然他们轮流阻止写入,但他们没有阅读任何东西,所以你可以溢出缓冲区并开始断开所有人的连接.
如果一个客户端有错误,其线程正在写入该客户端的客户端可能会获得异常,这意味着您将最终断开错误的用户.
因此,更好的解决方案是为每个客户端提供队列,并为读取器线程提供服务该队列的编写器线程.(然后你可以通过各种方式扩展它 - 对队列设置限制,以便人们不再试图与远远落后的人交谈,等等)
正如Anzel所指出的,除了每个客户端使用一个(或两个)线程之外,还有一种不同的设计服务器的方法:使用多路复用所有客户端事件的反应器.
Python 3.x有一些很好的内置库,但2.7只有笨重和过时asyncore
/ asynchat
低级别select
.
正如Anzel所说,Python SocketServer:发送给多个客户端有一个答案asyncore
,值得一读.但我实际上不会使用它.如果你想在Python 2.x中编写一个基于反应器的服务器,我要么使用更好的第三方框架,比如Twisted,要么找到或写一个直接位于其上的非常简单的框架select
.