Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我需要服务器向所有客户端(Python、套接字)发送消息_Python_Multithreading_Sockets_Networking_Tcp - Fatal编程技术网

我需要服务器向所有客户端(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将面临的问题。感谢您提供的详细答案!