我正在尝试一个简单的zmq
脚本,但是响应者不知何故没有收到第一条消息。
响应者如下:
def main():
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.connect("tcp://localhost:{}".format(5560))
print("connected ...")
while True:
# Wait for next request from client
message = socket.recv_pyobj()
#print (message)
print(message)
if __name__ == '__main__':
main()
我正在从另一个进程发送带有以下代码的请求:
def main():
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:{}".format(5560))
print("sending object")
socket.send_pyobj("ok")
print("done")
if __name__ == '__main__':
main()
有人知道为什么它没有到达吗?
答案 0 :(得分:1)
您必须在.bind()
代码段中添加REP
IP地址,而不是.connect()
。在REP / REQ pattern中,有请求和响应因素,因此您可以在响应者代码中抛出反馈。因此,您的代码将如下所示:
import zmq
def main():
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:5560")
while True:
message = socket.recv_pyobj()
print(message)
socket.send_string('Your message received.')
if __name__ == '__main__':
main()
import zmq
def main():
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://localhost:5560")
print("sending object")
socket.send_pyobj("ok")
message = socket.recv()
print(message)
if __name__ == '__main__':
main()
sending object
b'Your message received.'
ok
[注意]:
如果要发送没有任何响应的简单字符串,则使用PUSH / PULL或SUB / PUB模式代替REP / REQ更适合,并且也可以使用socket.send_string('ok')
代替在请求部分使用socket.send_pyobj('ok')
,在响应者中使用socket.recv()
而不是socket.recv_pyobj()
。
请注意,在.bind()
情况下,请勿使用localhost
字符串 Relevant Post 。
答案 1 :(得分:0)
Q :有人知道为什么它没有到达吗?
哦,我知道。
欢迎来到ZeroMQ零禅,有几个主要问题,这些问题决定着基于ZeroMQ的分布式计算系统如何以及如何工作。
如果对这个域感到陌生,可以从StackOverflow collection on ZeroMQ开始,并且愿意使用ZeroMQ或其他衍生工具( nanomsg 等),请确保不要错过Pieter HINTJENS的必读书“ Code Connected。Volume 1”。
在两个地方,可能会丢失(或基本上无法传递)消息:
.bind()
(第二名)的可用资源(端口)仅用于localhost
(内部端口抽象网络为vmci://
虚拟化)的严苛网络传输条件相关的问题
可固化:
def main():
context = zmq.Context()
socket = context.socket( zmq.REQ )
socket.setsockopt( zmq.LINGER, 0 ) # ALWAYS PREVENT BLOCKING
socket.setsockopt( zmq.IMMEDIATE, 1 ) # BLOCK UNTIL CONN-READY
#ocket.setsockpt( zmq.ZMQ_HANDSHAKE_IVL, ... ) # IF TWEAKING NETWORK-WIDE
# OR:
# a stone-age wait for the other part get started in a one-computer demo:
# sleep( 20 )
# :o)
socket.connect( "tcp://localhost:{}".format( 5560 ) )
print( "Will try to dispatch an object to Context() instance" )
socket.send_pyobj( "ok" )
print( ".send() method has returned from a blocking-call mode" )
...
#--------------------------------------------------------# ALWAYS
socket.close() # ALWAYS RELEASE RESOURCES
context.term() # ALWAYS RELEASE RESOURCES
# # ALWAYS (not all versions
# # have "friendly"
# # defeaults to rely
# # on others,
# # so be explicit)
#--------------------------------------------------------# ALWAYS
一侧,显然不一定是REP
,但由于while
,必须为.bind()
,因此在这里更合适,而另一侧只是.connect()
到已知的连接目标:
def main():
context = zmq.Context()
socket = context.socket( zmq.REP )
socket.setsockopt( zmq.LINGER, 0 ) # ALWAYS PREVENT BLOCKING
socket.setsockopt( zmq.IMMEDIATE, 1 ) # BLOCK UNTIL CONN-READY
#ocket.setsockpt( zmq.ZMQ_HANDSHAKE_IVL, ... ) # IF TWEAKING NETWORK-WIDE
socket.bind( "tcp://localhost:{}".format( 5560 ) )
print( ".bind() ...")
try:
while True: # Wait for next request from client:
message = socket.recv_pyobj()
print( message )
except:
print( "EXC'd" )
finally:
#----------------------------------------------------# ALWAYS
socket.unbind( "tcp://localhost:{}".format( 5560 ) ) # ALWAYS RELEASE PORT
socket.close() # ALWAYS RELEASE RESOURCES
context.term() # ALWAYS RELEASE RESOURCES
# # ALWAYS (not all versions
# # have "friendly"
# # defeaults to rely
# # on others,
# # so be explicit)
#----------------------------------------------------# ALWAYS
最后但并非最不重要的是,这将开始起作用,但由于REQ/REP
-行为原型的原则可能遗漏,因此将无限期地挂起。一个必须询问(REQ.send()
-s),另一个要回答的必须听问题REP.recv()
,但是也必须回答... {{1} } ,然后我们才能以两步探戈的方式前进两个,而ASKER也必须让答案听 REP.send("something")
。
然后只有这样,ASKER才能通过另一个REQ.recv()
发送另一个问题。
因此,您的发送REQ.send()
部分,主要是接收REQ
部分,在无限REP
循环中,都必须进行修改,以便接收第二和以后的消息,即使while True:{...}
-在一次射击后死亡,也从未听过REQ
的任何回答的情况下。