[英]How to implement simple ZeroMQ Pub-Sub communication between Python publisher and C++ subscriber?
[英]C++ and Python ZeroMQ 4.x PUB/SUB example does not work
我只能找到舊的C ++源代碼示例。 無論如何,我做了我的,基於他們。 這是我在python中的發布者:
import zmq
context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:5563")
while True:
msg = "hello"
socket.send_string(msg)
print("sent "+ msg)
sleep(5)
這是C ++中的訂閱者:
void * ctx = zmq_ctx_new();
void * subscriber = zmq_socket(ctx, ZMQ_SUB);
// zmq_connect(subscriber, "tcp://*:5563");
zmq_connect(subscriber, "tcp://localhost:5563");
// zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", sizeof(""));
while (true) {
zmq_msg_t msg;
int rc;
rc = zmq_msg_init( & msg);
assert(rc == 0);
std::cout << "waiting for message..." << std::endl;
rc = zmq_msg_recv( & msg, subscriber, 0);
assert(rc == 1);
std::cout << "received: " << (char * ) zmq_msg_data( & msg) << std::endl;
zmq_msg_close( & msg);
}
最初,我嘗試了zmq_setsockopt( subscriber, ZMQ_SUBSCRIBE, "", sizeof("") );
但是如果我不設置這個,我想我應該收到一切,對吧? 所以我對此發表了評論。
當我運行代碼時,我會永遠看到“等待消息......”。
我嘗試使用tcpdump
監聽TCP流量。 事實證明,當發布者打開時,我看到5563
端口上有很多垃圾,當我關閉發布者時,他們會停止。 當我嘗試PUSH/PULL
方案時,我可以在tcpdump
看到明文消息。 (我嘗試使用nodejs並使用c ++進行推送並且它有效)。
我能做錯什么?
我嘗試了.bind()
.connect()
, localhost
, 127.0.0.1
不同組合,但它們也不起作用。
更新 :我剛剛讀過我必須訂閱的東西,所以我做了zmq_setsockopt( subscriber, ZMQ_SUBSCRIBE, NULL, 0 );
訂閱一切,但我仍然沒有收到任何東西
PyZMQ的版本為17.0.0.b3,並具有ZeroMQ 4.2.3
C ++有ZeroMQ 4.2.2
更新2:
對4.2.3的更新都不起作用。
“如果我不設置這個,我想我應該收到一切,對吧? ”
不,這不是一個正確的假設。 你可能會喜歡我的其他ZeroMQ帖子的集合 ,關於{plain-string | unicode | 序列化} -issues和{performance- | traffic-} - 使用ZeroMQ實現異構分布式系統設計中可能遇到的實際策略(早期ZeroMQ版本的SUB
-side主題 - 過濾器處理,和/或更近期的PUB
-side處理) 。
(任何其他可伸縮形式通信原型模式,如觀察到的PUSH/PULL
,對訂閱策略不起作用,因此將獨立於針對設置主題過濾器列表的訂閱匹配處理。)
.send()
任何事情: 讓我們模擬一個快速的pythonic接收器,看看,如果發送者確實發送了任何東西:
import zmq
aContext = zmq.Context() # .new Context
aSUB = aContext.socket( zmq.SUB ) # .new Socket
aSUB.connect( "tcp://127.0.0.1:5563" ) # .connect
aSUB.setsockopt( zmq.LINGER, 0 ) # .set ALWAYS!
aSUB.setsockopt( zmq.SUBSCRIBE, "" ) # .set T-filter
MASK = "INF: .recv()-ed this:[{0:}]\n: waited {1: > 7d} [us]"
aClk = zmq.Stopwatch();
while True:
try:
aClk.start(); print MASK.format( aSUB.recv(),
aClk.stop()
)
except ( KeyboardInterrupt, SystemExit ):
pass
break
pass
aSUB.close() # .close ALWAYS!
aContext.term() # .term ALWAYS!
這應該報告PUB
-sender實際上是什么。 .send()
通過線路以及實際的消息到達.send()
時間(在[us]
,很高興ZeroMQ已經包含此工具用於調試和性能/延遲調整)。
如果您看到實時INF:
-messages確實在屏幕上顯示確認,請保持運行狀態,現在可以繼續執行下一步。
#include <zmq.h>
void *aContext = zmq_ctx_new();
void *aSUB = zmq_socket( aContext, ZMQ_SUB ); std::cout << "INF: .. zmq_ctx_new() done" << std::endl;
zmq_connect( aSUB, "tcp://127.0.0.1:5563" ); std::cout << "INF: .. zmq_connect() done" << std::endl;
zmq_setsockopt( aSUB, ZMQ_SUBSCRIBE, "", 0 ); std::cout << "INF: .. zmq_setsockopt( ZMQ_SUBSCRIBE, ... ) done" << std::endl;
zmq_setsockopt( aSUB, ZMQ_LINGER, 0 ); std::cout << "INF: .. zmq_setsockopt( ZMQ_LINGER, ... ) done" << std::endl;
int rc;
while (true) {
zmq_msg_t msg; /* Create an empty ØMQ message */
rc = zmq_msg_init (&msg); assert (rc == 0 && "EXC: in zmq_msg_init() call" );
std::cout << "INF: .. zmq_msg_init() done" << std::endl;
rc = zmq_msg_recv (&msg, aSUB, 0); assert (rc != -1 && "EXC: in zmq_msg_recv() call" );
std::cout << "INF: .. zmq_msg_recv() done: received [" << (char * ) zmq_msg_data( &msg ) << "]" << std::endl;
zmq_msg_close (&msg); /* Release message */
std::cout << "INF: .. zmq_msg_close()'d" << std::endl;
}
zmq_close( aSUB ); std::cout << "INF: .. aSUB was zmq_close()'d" << std::endl;
zmq_ctx_term( aContext ); std::cout << "INF: .. aCTX was zmq_ctx_term()'d" << std::endl;
zmq_setsockopt()
的返回值是zmq_setsockopt()
?
那么你應該使用""
而不是NULL
,它們是不同的。
zmq_setsockopt( subscriber, ZMQ_SUBSCRIBE, "", 0 );
正如API定義:
返回值
如果成功,
zmq_setsockopt()
函數將返回零。 否則它將返回-1並將errno
為下面定義的值之一。
...
運行PUB / SUB模式(無論語言)的正確配方是:
socket(zmq.PUB)
bind("tcp://127.0.0.1:5555")
encoded_topic = topic.encode()
encoded_msg = msg.encode()
send_multipart([encoded_topic, encoded_msg])
socket(zmq.SUB)
setsockopt(zmq.SUBSCRIBE, topic.encode())
connect("tcp://127.0.0.1:5555")
answer = recv_multipart()
enc_topic, enc_msg = answer
topic = enc_topic.decode()
msg = enc_msg.decode()
通常,步驟Pub-2 / Sub-3(即綁定/連接)和Pub-3 / Sub-5(即編碼/解碼或轉儲/加載)需要彼此互補才能使事情起作用。
這是我,問這個問題的人。
我設法通過在socket.bind("tcp://*:5563")
交換到socket.connect("tcp://dns_address_of_my_dcker_container:5564")
來實現工作 ,
和交換zmq_connect(subscriber, "tcp://localhost:5563")
以zmq_bind(subscriber, "tcp://*:5563")
在C ++中
我在網上找到的例子說我應該為發布者使用bind
並為訂閱者connect
,但它對我來說不會有任何作用。 有誰知道為什么?
ZeroMQ文檔說明如下:
zmq_bind()函數將套接字綁定到本地端點,然后接受該端點上的傳入連接。
zmq_connect()函數將套接字連接到端點,然后接受該端點上的傳入連接。
我不知道發生了什么變化,但它確實奏效了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.