ZeroMQ 2 REQ / REP允许嵌套通话

时间:2017-04-30 09:59:16

标签: python sockets zeromq

我希望发生以下情况:

有一个main_socket,任何人都可以与之交谈。

客户将发送" READ"等待"好的"在执行此操作之前从服务器。

当客户收到" OK"时,客户端将发送" WRITE",这意味着他们可以执行写操作。每个人都应该等待这个。所以我想到了另一个REQ / REP通道,它嵌套在主循环中。服务器将开始在write_socket上收听消息,当客户端写完消息时,它会向write_socket发送消息。

但不幸的是,这不起作用,我不明白为什么。

server.py

import time
import zmq

context = zmq.Context()
main_socket = context.socket(zmq.REP)
main_socket.bind("tcp://*:5555")

write_socket = context.socket(zmq.REP)
write_socket.bind("tcp://*:5556")

print("ready to receive")
while True:
    #  Wait for next request from client
    print("server receiving main")
    message = main_socket.recv()
    print("server received main", message)
    if message == b"WRITE":
        main_socket.send(b"WRITE")    
        print("server receiving write")
        message = write_socket.recv()
        print("server received write", message)
        write_socket.send(b"OK")    
    else:
        main_socket.send(b"OK")

client.py

import zmq
import time

context = zmq.Context()

#  Socket to talk to server
print("Connecting to main server…")
main_socket = context.socket(zmq.REQ)
main_socket.connect("tcp://localhost:5555")

print("Connecting to write server…")
write_socket = context.socket(zmq.REQ)
write_socket.connect("tcp://localhost:5556")

print("starting")
t1 = time.time()
for i in range(10000):
    print("client sending main", b"WRITE")
    main_socket.send(b"WRITE")
    print("client receiving main")
    message = main_socket.recv()
    print("client received main", message)

    print("client writing")
    print("writing...")
    print("client written")

    time.sleep(5)
    print("client sending write", b"WRITE")
    write_socket.send(b"WRITE")

    print("client receiving write")
    message = write_socket.recv()
    print("client received write", message)

这将打印以下内容:

服务器

ready to receive
server receiving main
server received main b'WRITE'
server receiving write

客户端

Connecting to read server…
Connecting to write server…
starting
client sending main b'WRITE'
client receiving main
client received main b'WRITE'
client writing
client written
client sending write b'WRITE'
client receiving write

如何让这个案子有效?

2 个答案:

答案 0 :(得分:2)

这只是一种预感,但是:问题可能是成功绑定0.0.0.0:5556即使localhost:5556还有127.0.0.1:5556的绑定套接字。< / p>

在这种情况下,绑定到0.0.0.0:5556的套接字将继续接收 127.0.0.1之外的任何其他地址的连接;并包括IPv6,但127.0.0.1:5556的连接尝试将被其他TCP服务器套接字accept编辑。

答案 1 :(得分:0)

您的设计理念在两个主要层次中是脆弱的:

所以即使只解决前者也会让你在后者中无能为力。

1运输级的固有脆弱性:
首先,关联的传输级别脆弱性(不获取先前发布的或外部使用的tcp-port)。鉴于此,人们可能会采取一些共址架构,将信令/消息传递服务转移到一些基于非tcp的传输类上,最有可能是其他一些{ inproc:// | ipc:// | vmci:// },但这并不能解决LAN / WAN分布式操作情况,加上,它仍然包含不解决第二种脆弱性的显着风险,这也需要一些强有力的解决方案:

[2] REQ/REP可扩展的正式通信模式的固有脆弱性: 任何严肃的应用程序设计都应该牢记,基本(原始)REQ/REP模式很容易陷入不可救助的相互死锁。 For details about this principal danger, kindly check my other posts on ZeroMQ, the REQ/REP deadlocks are quite frequent kind of collisions,但主要是在这里,如果应用程序对某种字段部署非常重要,那么请忘记使用&#34; naked&#34; - REQ/REP原语,否则您将应用程序自由落入分层FSA死锁中,这种死锁无法从应用程序内部自行检测到,因此无法被动态处理或抢救。

好消息是,ZeroMQ中还有许多其他简单的模式原型,作为构建模块,允许人们集成并快速构建强大的信令/消息传递应用程序基础。因此,请不要犹豫,使用更丰富的节点间信令/消息传递来增强您的应用程序,这不会相互死锁(任何基础设施范围内的任何一个僵局就越少......)。

这样,您的 try: / except: + assert 异常处理程序和非阻止 { .recv() | .send() } -s将保持控制,如果出现一些其他不期望的情况(并确保 - 迟早 - 将出现) - 体内