如果我用PyZMQ连接到一个不存在的套接字,我需要点击CTRLYC来停止这个程序。有人能解释一下为什么会这样吗?
import zmq
INVALID_ADDR = 'ipc:///tmp/idontexist.socket'
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(INVALID_ADDR)
socket.send('hello')
poller = zmq.Poller()
poller.register(socket, zmq.POLLIN)
conn = dict(poller.poll(1000))
if conn:
if conn.get(socket) == zmq.POLLIN:
print "got result: ", socket.recv(zmq.NOBLOCK)
else:
print 'got no result'
最佳答案
这个问题也是GitHub上的一个pyzmq问题。我将在这里解释一下我的解释(我希望这是适当的,我对此还不太熟悉):
一般规则:如果有疑问,zeromq程序末尾的挂起是由于延迟造成的。
这里的挂起是由LINGER socket选项引起的,它发生在脚本末尾的垃圾收集期间调用的context.term()
方法中。zeromq文档中的延迟行为是posted,但简单地说,在删除消息之前,关闭套接字后等待队列中的任何挂起消息被处理是一个超时(以毫秒为单位)。默认行为是LINGER=-1
,这意味着永远等待。
在这种情况下,由于从未启动对等方,因此当套接字尝试关闭时,您试图发送的“hello”消息仍在发送队列中等待。使用LINGER=-1
,ZeroMQ将等到对等机准备好接收该消息后再关闭。如果在这个脚本明显挂起时,将一个ReSocket绑定到“IPC://TMP/IDOnTeXist.Socket”,消息将被传递,脚本将完全退出。
如果不希望脚本等待(如已放弃获取答复的print语句所示),请将LINGER设置为任何非负值(例如socket.linger = 0
),等待指定毫秒数后将返回context.term()
。
我应该注意到,无效的\u ADDR变量名表明理解到还没有侦听器的接口的连接无效-这是不正确的。zeromq允许绑定/连接事件以任何顺序发生,如上面描述的行为所示,即在发送脚本阻塞term()
时将REP套接字绑定到接口。