【问题标题】:Python 3: Socket server send to multiple clients with sendto() functionPython 3:套接字服务器使用 sendto() 函数发送到多个客户端
【发布时间】:2015-09-14 04:27:54
【问题描述】:

我有一个设置了套接字和线程的服务器,当我将多个客户端连接到它时,如果一个客户端发送一条消息,服务器会将相同的消息重复给它,而不是所有其他连接的客户端。例如:

#server terminal
Server is connected on 8000
('127.0.0.1', 50328) is Connected
('127.0.0.1', 50329) is Connected
Received Message b'hi\n'

#Client 1 terminal
#input
[user1]hi
#returns:
[user1] b'hi\nhi\n'[user1]

#Client 2 terminal
#doesn't return anything, just sits at the prompt
[user2]

服务器的相关代码是:

def clientHandler():
    c, addr = s.accept() 
    print(addr, "is Connected")
    if addr not in clients:
        clients.append(addr)
    try:
        while True:
            data = c.recv(1024)
            if not data: 
                break 
            print("Received Message ", repr(data))
            for client in clients:
                c.sendto(data, client)
    except:
        print("Error. Data not sent.")

我已阅读以下资料,但无济于事:

python tcp server sending data to multiple clients

https://docs.python.org/3/library/socket.html

我必须怎么做才能让它通过服务器将 user1 的消息发送给所有其他用户?

编辑 1: 所有server.py代码:

from socket import *
from threading import Thread

clients = []

def clientHandler():
    c, addr = s.accept() 
    print(addr, "is Connected")
    if addr not in clients:
        clients.append(addr)
    try:
        while True:
            data = c.recv(1024)
            if not data: 
                break 
            for client in clients:
                c.sendto(data, client)
    except:
        print("Error. Data not sent to all clients.")

HOST = '' #localhost
PORT = 8000

s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)

print("Server is running on "+ str(PORT))

#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()

for i in range(5): 
    Thread(target=clientHandler).start()

s.close()

【问题讨论】:

  • 您是否为每个新客户端使用多个线程?如果是这样,请同时向我们展示相关代码
  • 如果它真的将数据发送给所有客户端,你会不会陷入无限发送循环?接收数据 --> 发送给所有主机 --> 他们都接收数据 --> 再次发送给所有主机,以此类推?
  • 我不确定。我从服务器向所有客户端发送数据的方式是使用 for 循环。我认为,一旦它遍历客户列表中的所有可能性,它就会停止。没有?
  • 它是一个客户端/服务器模型,我不认为客户端会发回他们收到的所有内容。服务器是将数据发送到多个客户端的那个,而不是相反,我猜
  • 是的,这是正确的。例如,我的服务器是从客户端 1 接收数据的服务器,然后必须将该数据发送到客户端列表中的每个其他客户端

标签: python multithreading sockets python-3.x


【解决方案1】:

我在您的代码中发现了一些问题 -

  1. 你正在启动 clientHandler 线程,但是你没有让主线程加入任何线程,这可能会导致主线程在子线程完成处理之前死掉,我想你会想要保存 Thread 对象你创建一个变量,然后让它们加入主线程。

  2. 您应该首先等待接受来自客户端的连接(在处理函数之外),而不是直接创建客户端处理程序,一旦获得连接,将其添加到客户端列表并将其发送到客户端处理程序。

  3. 在您的代码中 - for client in clients: c.sendto(data, client) m 这会将数据发送到所有客户端,而不是您应该检查 client 是否不是该线程正在服务的 client,通过检查 addr线程正在服务中。

示例更改 -

from socket import *
from threading import Thread

clients = []

def clientHandler(c, addr):
    global clients
    print(addr, "is Connected")
    try:
        while True:
            data = c.recv(1024)
            if not data: 
                break 
            for client in clients:
                if addr != client:
                    c.sendto(data, client)
    except:
        print("Error. Data not sent to all clients.")

HOST = '' #localhost
PORT = 8000

s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(5)

print("Server is running on "+ str(PORT))

#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
#Thread(target=clientHandler).start()
trds = []

for i in range(5): 
    c, addr = s.accept() 
    clients.append(addr)
    t = Thread(target=clientHandler, args = (c, addr))
    trds.append(t)
    t.start()

for t in trds:
    t.join()

s.close()

【讨论】:

  • 这似乎在一定程度上起作用。现在,它只是将消息返回给发送它的客户端,而不是其他客户端
  • 您确定您使用的是我粘贴的完整代码吗?包括对 clientHandler() 函数的更改?它是 !=,而不是 ==
  • 你能在 addr 的 sendto 函数之前添加一个 print 语句并检查它发送到的 wat 地址吗?
  • 第一个客户端输出:('127.0.0.1', 50835) 和第二个('127.0.0.1', 50836)
  • 那个客户的地址是?
猜你喜欢
  • 2016-07-17
  • 2020-06-01
  • 1970-01-01
  • 2018-07-29
  • 2015-10-25
  • 2013-04-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
相关资源
最近更新 更多