多线程套接字连接/队列

2024-01-09

SocketClientThread 参考:http://eli.thegreenplace.net/2011/05/18/code-sample-socket-client-thread-in-python/ http://eli.thegreenplace.net/2011/05/18/code-sample-socket-client-thread-in-python/

Eli 提供了这个通用示例,说明如何在线程内管理套接字客户端,并使用队列模块与主作用域进行通信。 (再次感谢伊莱!)

一个线程工作得很好,但我想做的是同时管理多个 SocketClientThread 对象。

连接后,当我尝试向第二个对象发送数据时,它告诉我 Socket Client Thread.socket 没有 sendall 属性,因此我认为套接字已被清空。

1和2的服务器都成功接收连接,但触发错误的是第二个服务器的发送命令。

如何将此类与多个对象重复使用?

这是输出:

$ python testmodule.py
('sct1: ', 1, None)
('sct1: ', 1, 'tuxy')
('sct2: ', 1, None)
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 522, in __bootstrap_inner
    self.run()
  File "testmodule.py", line 59, in run
    self.handlers[cmd.type](cmd)
  File "testmodule.py", line 115, in _handle_SEND
    self.socket.sendall(header + cmd.data)
AttributeError: 'NoneType' object has no attribute 'sendall'

这是我尝试打开两者的代码:

if __name__ == "__main__":
    sct1 = SocketClientThread()
    sct1.start()
    sct1.cmd_q.put(ClientCommand(ClientCommand.CONNECT, ('', 50007)))
    reply = sct1.reply_q.get(True)
    sct1.cmd_q.put(ClientCommand(ClientCommand.SEND, "hellothere from sct1"))
    reply = sct1.reply_q.get(True)
    print('sct1: ', reply.type, reply.data)
    sct1.cmd_q.put(ClientCommand(ClientCommand.RECEIVE, "hellothere from sct1"))
    reply = sct1.reply_q.get(True)
    print('sct1: ', reply.type, reply.data)

    sct2 = SocketClientThread()
    sct2.start()
    sct2.cmd_q.put(ClientCommand(ClientCommand.CONNECT, ('', 50008)))
    reply = sct2.reply_q.get(True)
    print('sct2 connect: ', reply.type, reply.data)
    sct2.cmd_q.put(ClientCommand(ClientCommand.SEND, "hellothere from sct2"))
    reply = sct2.reply_q.get(True)
    print('sct2 send: ', reply.type, reply.data)
    sct2.cmd_q.put(ClientCommand(ClientCommand.RECEIVE, "hellothere from sct2"))
    reply = sct2.reply_q.get(True)
    print('sct2: ', reply.type, reply.data)

    #close connection 1
    sct1.cmd_q.put(ClientCommand(ClientCommand.CLOSE))
    reply = sct1.reply_q.get(True)
    print('sct1 close: ', reply.type, reply.data)

    #close connection 2
    sct2.cmd_q.put(ClientCommand(ClientCommand.CLOSE))
    reply = sct2.reply_q.get(True)
    print('sct2 close: ', reply.type, reply.data)

看起来您在示例代码中发现了一个错误:-) 正如您所指出的,该错误仅在同时创建多个线程时才会发生。这是因为Queue.Queue()默认参数仅在定义类时构造一次 - 实际上是 Python 中相当常见的错误,但通常发生在列表中。

我已经更新了帖子,但更改在这里:

def __init__(self, cmd_q=None, reply_q=None):
    super(SocketClientThread, self).__init__()
    self.cmd_q = cmd_q or Queue.Queue()
    self.reply_q = reply_q or Queue.Queue()
    self.alive = threading.Event()
    self.alive.set()
    self.socket = None

    self.handlers = {
        ClientCommand.CONNECT: self._handle_CONNECT,
        ClientCommand.CLOSE: self._handle_CLOSE,
        ClientCommand.SEND: self._handle_SEND,
        ClientCommand.RECEIVE: self._handle_RECEIVE,
    }

请注意现在队列是如何初始化的 - 这是避免可变默认参数陷阱的常见习惯用法。

您的示例代码现在对我有用


附:在我的 Windows 机器上,我必须指定主机(即使它是localhost)在客户端成功连接。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程套接字连接/队列 的相关文章

随机推荐