ZMQ(PUB-SUB)
服務端不管客戶端這邊有沒有接收到數據,只負責發送。客戶端不能發送數據,只負責接收。
(1)一個發佈者,多個訂閱者的關係,1:n;
(2)只有設置了與服務端發送消息相同訂閱類型的客戶端才能接收到消息
(3)服務端可以綁定多個端口
注:使用SUB設置一個訂閱時,使用zmq_setsockopt()對消息進行過濾
C++示例代碼:
服務端:
//server
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<zmq.h>
#include<assert.h>
using namespace std;
int main()
{
void *context = zmq_ctx_new();
void *socket = zmq_socket(context,ZMQ_PUB);
int ret = zmq_bind(socket, "tcp://*:6666");
assert(ret == 0);
ret = zmq_bind(socket, "tcp://*:5555"); //綁定另一個端口5555
assert(ret == 0);
int i = 0; //消息計數器
while (1)
{
Sleep(10);
char sendBuf[1024] = {0};
sprintf(sendBuf, "[Server] : server = %d", i++);
int sentBytes = zmq_send(socket, sendBuf, strlen(sendBuf), 0);
if (sentBytes > 0)
{
printf("%s\n", sendBuf);
}
}
zmq_close(socket);
zmq_ctx_destroy(context);
system("pause");
return 0;
}
客戶端1:(接收6666端口消息)
//客戶端1:接收服務端 6666端口的消息
#include<iostream>
#include<thread>
#include<zmq.h>
#include<assert.h>
using namespace std;
void Recv1(void *arg); //客戶端接收線程1
void Recv2(void *arg); //客戶端接收線程2
int main()
{
void *context = zmq_ctx_new();
assert(context != NULL);
void *socket = zmq_socket(context,ZMQ_SUB);
assert(socket != NULL);
int ret = zmq_connect(socket, "tcp://localhost:6666");
assert(ret == 0);
ret = zmq_setsockopt(socket, ZMQ_SUBSCRIBE, "[Server]", 8);
assert(ret == 0);
thread th1(Recv1,socket);
thread th2(Recv2,socket);
th1.join();
th2.join();
zmq_close(socket);
zmq_ctx_destroy(context);
system("pause");
return 0;
}
void Recv1(void *arg) //客戶端接收線程1
{
void *socket = arg;
while(1)
{
char recvBuf[1024] = { 0 };
Sleep(1);
int recvBytes = zmq_recv(socket, recvBuf, sizeof(recvBuf)-1, 0);
if (recvBytes > 0)
{
printf("[Client] : Recv1--------------:%s\n", recvBuf);
}
}
}
void Recv2(void *arg) //客戶端接收線程2
{
void *socket = arg;
while (1)
{
char recvBuf[1024] = { 0 };
Sleep(1);
int recvBytes = zmq_recv(socket, recvBuf, sizeof(recvBuf)-1, 0);
if (recvBytes > 0)
{
printf("[Client] : Recv2--------------:%s\n", recvBuf);
}
}
}
客戶端2:接收5555端口消息
//客戶端2:接收5555端口
#include<iostream>
#include<thread>
#include<zmq.h>
#include<assert.h>
using namespace std;
void Recv3(void *arg); //客戶端接收線程3
int main()
{
void *context = zmq_ctx_new();
void *socket = zmq_socket(context, ZMQ_SUB);
int ret = zmq_connect(socket, "tcp://localhost:5555");
assert(ret == 0);
thread th3(Recv3, socket);
th3.join();
zmq_close(socket);
zmq_ctx_destroy(context);
system("pause");
return 0;
}
void Recv3(void *arg) //客戶端接收線程3
{
void *socket = arg;
int ret = zmq_setsockopt(socket, ZMQ_SUBSCRIBE, "", 0);
assert(ret == 0);
while (1)
{
char recvBuf[1024] = { 0 };
Sleep(1);
int recvBytes = zmq_recv(socket, recvBuf, sizeof(recvBuf)-1, 0);
if (recvBytes > 0)
{
printf("[Client] : Recv3--------------:%s\n", recvBuf);
}
}
}
測試結果:
先運行兩個客戶端,再運行服務端,兩個客戶端如果設置的過濾一致,那它們接收到的消息應該相同;