【问题标题】:Receiving zmq messages on background thread fails on Windows在 Windows 上在后台线程上接收 zmq 消息失败
【发布时间】:2019-09-09 03:51:17
【问题描述】:

我正在尝试通过在后台线程上接收消息同时使用控制台输入发送消息来设置两个对等方之间使用 zmq.PAIR 的异步通信的 hello world 样式示例:

server.py

import zmq
import threading

context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.bind('tcp://*:5556')

def print_incoming_messages():
    while True:
        msg = socket.recv_string()
        print(f'Message from client: {msg}')

recv_thread = threading.Thread(target=print_incoming_messages)
recv_thread.start()

while True:
    msg = input('Message to send: ')
    socket.send_string(msg)

client.py

import zmq
import threading

context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.connect('tcp://127.0.0.1:5556')

def print_incoming_messages():
    while True:
        msg = socket.recv_string()
        print(f'Message from server: {msg}')

recv_thread = threading.Thread(target=print_incoming_messages)
recv_thread.start()

while True:
    msg = input('Message to send: ')
    socket.send_string(msg)

这在 Linux 机器上完全可以正常工作,但在从 Windows 10 命令提示符运行时,socket.send_string 会阻止任一进程。造成这种差异的原因是什么?

套接字设置正确,刷新所有输出没有区别。读取本身也可以按预期工作,可以通过在浏览器中导航到 127.0.0.1:5556 来验证。查看 Wireshark 中的环回接口也可以发现连接设置正确,但没有发送任何消息。

但是,如果我在客户端注释掉 recv_thread.start(),消息将通过 Wireshark 进行验证,这表明 socket.recv_string 以某种方式阻止了套接字发送,即使它在 Linux 上没有这样做.

我还可以通过使用两组 PUSH/PULL(参见this answer)来实现所需的行为,但这并不能完全帮助解释手头示例中发生的情况。

这适用于两个系统上的 Python 3.7.1、pyzmq 18.0.0 和 libzmq 4.3.1。

【问题讨论】:

    标签: python multithreading sockets zeromq pyzmq


    【解决方案1】:

    zmq 套接字不是线程安全的,因此不应期望在不同线程中的同一套接字上运行 send 和 recv 。不同平台上的不同线程行为可能会导致您看到的行为差异,但由于 zmq 套接字的线程不安全,此代码最终也可能导致段错误。使用Lock 可能会解决问题。

    附带说明一下,PAIR 是一种很少使用的套接字类型,通常不用于生产或进程间通信。大多数真实世界的 PAIR 实例都是用于线程间通信的 inproc 套接字。例如,PAIR 在重新连接时可能会出现奇怪的行为。使用 PUSH-PULL 进行单向通信或使用 DEALER-DEALER 进行双向通信可能会以一种更符合预期的方式运行。

    【讨论】:

    • 谢谢。是否有参考在某处详细讨论非线程安全? pyzmq.readthedocs.io/en/latest/api/zmq.html 提到了一些线程安全问题,但据我所知,socket 不会发生什么(尽管通常可以找到有关 ZeroMQ 的一些信息,从中可以推断出一些关于这种情况的信息在 pyzmq 中)。在 PUSH-PULL 示例中,您需要两侧都有两个套接字(参见引用的答案),对吗?使用 DEALER-DEALER,如果您在不同的线程上阅读和发送,您不会遇到同样的问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 2023-03-24
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多