Не удается получить сообщения zmq в фоновом потоке в Windows - PullRequest
1 голос
/ 18 апреля 2019

Я пытаюсь настроить пример приветственного мирового стиля асинхронной связи между двумя одноранговыми узлами с помощью zmq.PAIR, получая сообщения в фоновом потоке, используя консольный ввод для отправки сообщений:

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, но socket.send_string блокируется в любом процессе при запуске из командной строки Windows 10. В чем причина этого несоответствия?

Разъем настроен правильно, промывка всех выходов не имеет значения. Само чтение также работает, как и ожидалось, что можно проверить, перейдя к 127.0.0.1:5556 в браузере. Просмотр интерфейса обратной связи в Wireshark также показывает, что соединение установлено правильно, но сообщения не отправляются.

Если я закомментирую recv_thread.start() в клиенте, однако, сообщения отправляются через, что может быть проверено в Wireshark, что предполагает, что каким-то образом socket.recv_string блокирует отправку сокета, даже если это не происходит в Linux .

Я также могу достичь желаемого поведения, используя два набора PUSH / PULL (ср. этот ответ ), но это не совсем помогает объяснить, что происходит в данном примере.

Это на Python 3.7.1, pyzmq 18.0.0 и libzmq 4.3.1 в обеих системах.

1 Ответ

2 голосов
/ 21 апреля 2019

сокеты zmq не являются потокобезопасными, поэтому не следует ожидать, что выполнение send и recv на одном и том же сокете в разных потоках будет работать.Различное поведение потоков на разных платформах может быть причиной различий в поведении, которое вы видите, но этот код может также привести к ошибкам в конечном итоге из-за небезопасности потоков в сокетах zmq.Использование Lock может решить проблему.

В качестве примечания, PAIR - это редко используемый тип сокетов, и он не часто предназначен для использования в производственной или межпроцессной коммуникации.Большинство реальных экземпляров PAIR представляют собой inproc сокеты для связи между потоками.Например, у PAIR может быть странное поведение при переподключении.Использование PUSH-PULL для односторонней связи или DEALER-DEALER для двусторонней связи может вести себя более ожидаемым образом.

...