【问题标题】:Multiple sockets created when accepting connection, but data is treated as if it had been sent by the first connected client接受连接时创建多个套接字,但数据被视为已由第一个连接的客户端发送
【发布时间】:2018-04-20 17:29:27
【问题描述】:

我正在开发一个类似于多用户聊天的项目,该项目应该同时处理来自多个客户端的连接。当客户端连接时,我accept() 连接并将其传递给它自己的线程上的Client 类,该类使用self.socket.recv(1024) 循环处理传入数据。当数据进入时,它存储在一个名为data-queue 的列表中。然后我将此客户端存储在Clients 的列表中。

每 100 毫秒,我会遍历 Clients 列表中的每个 Client 并检查 data-queue 列表是否为空。如果不是,我将通过pop()-ing 列表和客户地址打印我得到的任何内容。

问题是,如果有多个客户端同时连接,只有第一个连接的Client 才能获得他们发送的所有数据,就像是他发送的一样。

如果客户端 A 发送“嗨!”并且客户端 B 发送“您好!”,服务器只是读取,就好像客户端 A 是发送两个“您好!”的人一样。和“你好!”客户B一直保持沉默。如果客户端 A 断开连接,来自其他客户端的所有输入都被视为由第一个剩余的客户端发送(在这种情况下,客户端 B,因为客户端 A 已离开),依此类推。

会是什么?

编辑

源代码有点像这样:

CLIENTS = []

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', 1515))
    s.listen(5)
    runCycle()
    while True:
        CLIENTS.append(client(s.accept()))
        CLIENTS[len(CLIENTS)-1].start()

class client(threading.Thread):
    dataQueue = []

    def __init__(self, (socket, address)):
        self.socket = socket
        self.address = address
        threading.Thread.__init__(self)

    def run(self):
        self.data = ""
        while True:
            self.data = self.socket.recv(1024)
            if not self.data:
                break
            dataQueue.append(self.address + " " + self.data)
            self.data = ""

def runCycle():
    threading.Timer(0.1, runCycle).start()
    for c in CLIENTS:
        if len(c.dataQueue) > 0:
            print c.dataQueue.pop()

main()

【问题讨论】:

  • 信息太少,能不能发下客户的代码
  • 那里!谢谢~

标签: python sockets


【解决方案1】:
class client(threading.Thread):
    dataQueue = []

这意味着dataQueue 是静态的,[] 的同一个实例在线程之间共享。在这种情况下迭代客户端是没有结果的,你可以从任何客户端对象中读取它:

>>> class C(object):
...   a = []
... 
>>> c1, c2 = C(), C()
>>> c1.a.append(1)
>>> c2.a
[1]

dataQueue 移动到__init__ 以解决此问题。

class client(threading.Thread):

    def __init__(self, (socket, address)):
        self.socket = socket
        self.address = address
        self.dataQueue = []
        threading.Thread.__init__(self)

请注意保护self.dataQueuea lock。奇怪的是列表不是线程安全的。

【讨论】:

  • 哦!我认为在类中声明的变量就像私有 C++ 类变量一样工作。今天我学习了。你救了我,非常感谢!
猜你喜欢
  • 2011-03-22
  • 2013-08-27
  • 2013-02-17
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多