簡體   English   中英

C ++和Python ZeroMQ 4.x PUB / SUB示例不起作用

[英]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()localhost127.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 ,對訂閱策略不起作用,因此將獨立於針對設置主題過濾器列表的訂閱匹配處理。)


步驟0:首先測試發送部分RTO,如果是.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確實在屏幕上顯示確認,請保持運行狀態,現在可以繼續執行下一步。


第1步:接下來測試接收部分代碼:

#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模式(無論語言)的正確配方是:

酒吧

  1. socket(zmq.PUB)
  2. bind("tcp://127.0.0.1:5555")
  3. 編碼(通常只是字符串的encode(),但你也可以壓縮()或轉儲()對象甚至兩者) encoded_topic = topic.encode() encoded_msg = msg.encode()
  4. send_multipart([encoded_topic, encoded_msg])

  1. socket(zmq.SUB)
  2. setsockopt(zmq.SUBSCRIBE, topic.encode())
  3. connect("tcp://127.0.0.1:5555")
  4. answer = recv_multipart()
  5. 解碼答案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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM