SocketClientThread参考:http://eli.thegreenplace.net/2011/05/18/code-sample-socket-client-thread-in-python/
Eli提供了如何在线程内管理套接字客户端以及使用Queue模块与主作用域通信的通用示例。 (再次感谢Eli!)
一个线程运行良好,但我想做的是同时管理多个SocketClientThread对象。
连接后,当我尝试将数据发送到第二个对象时,它告诉我SocketClientThread.socket没有sendall属性,所以我认为套接字被删除了。
1和2的服务器都成功接收连接,但是第二个服务器的send命令会触发错误。
如何在多个对象中重复使用此类?
这是输出:
$ 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)
答案 0 :(得分:2)
看起来你在示例代码中发现了一个错误:-)只有当你注意到同时创建了多个线程时,才会发生错误。这是因为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,
}
注意队列现在是如何初始化的 - 这是避免可变默认参数getcha的常用习惯用法。
您的示例代码现在适用于我
P.S。在我的Windows机器上,我必须在客户端中指定主机(即使它是localhost
)才能成功连接。
答案 1 :(得分:0)
对于使用套接字进行线程/进程之间通信的多线程编程,我建议尝试ZeroMQ。它使异步I / O变得容易并且内置了自动排队功能。让多个线程同时向GUI线程发送消息是微不足道的,并且消息在到达时排队并处理。我希望这会有所帮助。