Qt with ZeroMQ publish subscribe pattern
我想将ZeroMQ(4.1.2)与Qt(5.2.1)一起使用。
想法是拥有zmq pub / sub(服务器在外部),而sub是qt app。
目前在Qt应用中收到一次运行,有人可以删除提示吗?
是否可以通过其他方式实现ZeroMQ接收器?
目前,我的代码如下:
主窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_pushButton_clicked(); void readZMQData(); private: Ui::MainWindow *ui; QSocketNotifier *qsn; void *context; void *subscriber; }; |
主窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); /***** ZMQ *****/ context = zmq_ctx_new (); subscriber = zmq_socket (context, ZMQ_SUB); int rc = zmq_connect (subscriber,"tcp://localhost:5556"); char *filter =""; rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE,filter, strlen (filter)); unsigned int fd=0; size_t fd_size = sizeof(fd); rc = zmq_getsockopt(subscriber,ZMQ_FD,&fd,&fd_size); qsn = new QSocketNotifier(fd, QSocketNotifier::Read, this); connect(qsn, SIGNAL(activated(int)), this, SLOT(readZMQData()), Qt::DirectConnection); } MainWindow::~MainWindow() { zmq_close (this->subscriber); zmq_ctx_destroy (this->context); delete ui; } void MainWindow::readZMQData() { qsn->setEnabled(false); qDebug() <<"Got data!"; int events = 0; std::size_t eventsSize = sizeof(events); zmq_getsockopt(subscriber,ZMQ_EVENTS, &events, &eventsSize); if(events & ZMQ_POLLIN){ qDebug() <<" ====== Data to read ======"; char *string = s_recv(subscriber); qDebug() <<"DATA:" << string; free(string); } qsn->setEnabled(true); } |
服务器应用程序是(来自ZeroMQ示例):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include"zhelpers.h" int main (void) { // Prepare our context and publisher void *context = zmq_ctx_new (); void *publisher = zmq_socket (context, ZMQ_PUB); int rc = zmq_bind (publisher,"tcp://*:5556"); assert (rc == 0); // Initialize random number generator srandom ((unsigned) time (NULL)); while (1) { // Get values that will fool the boss int zipcode, temperature, relhumidity; zipcode = randof (100000); temperature = randof (215) - 80; relhumidity = randof (50) + 10; // Send message to all subscribers char update [20]; sprintf (update,"%05d %d %d", zipcode, temperature, relhumidity); s_send (publisher, update); } zmq_close (publisher); zmq_ctx_destroy (context); return 0; } |
第一个帮助的tnx,
我发现了问题,当ZeroMQ通知有消息要读取时,您需要全部读取它们,而不仅仅是第一条。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | void MainWindow::readZMQData(int fd) { qsn->setEnabled(false); int events = 0; std::size_t eventsSize = sizeof(events); zmq_getsockopt(subscriber,ZMQ_EVENTS, &events, &eventsSize); if(events & ZMQ_POLLIN){ qDebug() <<" ====== Data to read ======"; char *string; // THIS IS THE TRICK! READ UNTIL THERE IS MSG while((string = s_recv_nb(subscriber)) != NULL){ qDebug() <<"DATA:" << string; free(string); } } qsn->setEnabled(true); } |
套接字通知程序看起来应该可以工作。 您是否已阅读有关正确处理文档的文档? 尤其是如果您使用的是Windows,则在进行读取...禁用,读取等操作时,似乎有特殊的处理方法。
http://doc.qt.io/qt-5/qsocketnotifier.html#details
希望能有所帮助。
由于尚不清楚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void MainWindow::readZMQData() { qsn->setEnabled(false); int events = 0; std::size_t eventsSize = sizeof(events); zmq_getsockopt(subscriber,ZMQ_EVENTS, &events, &eventsSize); if(events & ZMQ_POLLIN){ qDebug() <<" ====== Data to read ======"; char *string; int64_t more; size_t more_size = sizeof (more); do { /* Create an empty ?MQ message to hold the message part */ zmq_msg_t part; int rc = zmq_msg_init (&part); assert (rc == 0); rc = zmq_msg_recv (&part, subscriber, 0); assert (rc != -1); /* Determine if more message parts are to follow */ rc = zmq_getsockopt (subscriber, ZMQ_RCVMORE, &more, &more_size); assert (rc == 0); string = (char*) zmq_msg_data(&part); qDebug() << QString(string) ; // <<"more" << more; zmq_msg_close (&part); } while (more); } qsn->setEnabled(true); } |
还有一点要注意:在Windows 64的情况下,当传递ZMQ_FD option_val的本地地址时,文件描述符