如何在Python中实现多线程socket.recv()?
我有很多设备需要获取状态更新。现在我只有一个套接字对象,而通过socket.recv()这个方法就能获取状态。在单线程的应用中,这一切都很顺利:
class Device:
def receive(self):
log.debug("receive waiting: %r", self.device_id)
try:
packet = self.socket.recv(255)
except Exception as e:
self.report_socket_error(e)
self.reconnect()
log.debug("received response: %r", self.device_id)
d = Device()
d.connect()
while True:
d.receive()
但是,当把相同的代码放进一个线程类中时,就出现了死锁和一些奇怪的行为。即使加了锁也没有改变什么。我追踪问题发现是socket.recv()这个调用出了问题……那么,如何实现多个线程,每个线程独占一个套接字(一个线程只负责一个套接字),并且能够同时等待数据呢?
提前谢谢你们!
2 个回答
0
你需要从多少个不同的套接字读取数据呢?
- 如果答案是“只有一个”,那么就只用一个线程。再加一个线程对你没有任何帮助,反而会让事情变得更复杂,就像你发现的那样。
如果答案是“多个”,那么一种组织方式就是每个套接字用一个线程。
recv
是一个阻塞操作,这使得使用线程来组织代码变得很有吸引力。每个线程都有自己的套接字,可以随时读取数据。这样做应该不会出现问题或死锁。只要没有共享资源,就不需要使用锁。即使你需要共享一些资源(比如日志记录、某些数据存储等),也不要仅仅使用简单的锁——Python 提供了更高级的工具,比如
Queue
模块。
0
我知道这并没有直接回答你关于如何解决死锁问题的提问,但看起来在你的情况下,使用线程可能有点多余:
你可以只用一个线程,利用 select()
来找出哪个套接字有可用的数据,然后处理这些数据。除非处理数据的时间很长,或者你的协议比较复杂,使用 select
应该就足够了,这样可以避免所有与线程相关的问题。
想了解更多细节,可以看看这个链接:http://docs.python.org/howto/sockets.html#non-blocking-sockets。