1. 下载zeromq
C: git clone http://github.com/zeromq/libzmq;
2. 编译
编译zmqlib:启动开始菜单 vs2017下的x64 Native Tools Command Prompt for VS 2017。
mkdir -p src\libzmq\build;
cd src\libzmq\build;
cmake ..
vs2017打开ZeroMQ.sln。编译。
3.使用:
A.publisher-subscriber模式
server:
#include
#include
#include
#include
#include
#include
#if (!defined (WIN32))
# include
#endif
#if (defined (WIN32))
# include
#endif
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
srand((unsigned) time (NULL));
while (1) {
// Get values that will fool the boss
int zipcode, temperature, relhumidity;
zipcode = rand()%(100000);
temperature = rand()%(215) - 80;
relhumidity = rand()%(50) + 10;
// Send message to all subscribers
char update [20];
sprintf (update, "%05d %d %d", zipcode, temperature, relhumidity);
zmq_send (publisher, update, strlen (update), 0);
}
zmq_close (publisher);
zmq_ctx_destroy (context);
return 0;
}
client:
#include
#include
#include
#include
#include
#include
#if (!defined (WIN32))
# include
#endif
#if (defined (WIN32))
# include
#endif
int main (int argc, char *argv [])
{
// Socket to talk to server
printf ("Collecting updates from weather server...\n");
void *context = zmq_ctx_new ();
void *subscriber = zmq_socket (context, ZMQ_SUB);
int rc = zmq_connect (subscriber, "tcp://localhost:5556");
assert (rc == 0);
// Subscribe to zipcode, default is NYC, 10001
const char *filter = (argc > 1)? argv [1]: "10001 ";
rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE,
filter, strlen (filter));
assert (rc == 0);
// Process 100 updates
int update_nbr;
long total_temp = 0;
for (update_nbr = 0; update_nbr < 100; update_nbr++) {
char buffer [256];
int size = zmq_recv (subscriber, buffer, 255, 0);
if (size == -1)
continue;
buffer[size] = '\0';
int zipcode, temperature, relhumidity;
sscanf (buffer, "%d %d %d",
&zipcode, &temperature, &relhumidity);
total_temp += temperature;
}
printf ("Average temperature for zipcode '%s' was %dF\n",
filter, (int) (total_temp / update_nbr));
zmq_close (subscriber);
zmq_ctx_destroy (context);
return 0;
}
B.request-response模式:
server:
#include
#include
#include
#include
#if (!defined (WIN32))
# include
#endif
#if (defined (WIN32))
# include
#endif
int main (void)
{
// Socket to talk to clients
void *context = zmq_ctx_new ();
void *responder = zmq_socket (context, ZMQ_REP);
int rc = zmq_bind (responder, "tcp://*:5555");
assert (rc == 0);
while (1) {
char buffer [10];
zmq_recv (responder, buffer, 10, 0);
printf ("Received Hello\n");
Sleep (1); // Do some 'work'
zmq_send (responder, "World", 5, 0);
}
return 0;
}
client:
#include
#include
#include
int main (void)
{
printf ("Connecting to hello world server...\n");
void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
zmq_connect (requester, "tcp://localhost:5555");
int request_nbr;
for (request_nbr = 0; request_nbr != 10; request_nbr++) {
char buffer [10];
printf ("Sending Hello %d...\n", request_nbr);
zmq_send (requester, "Hello", 5, 0);
zmq_recv (requester, buffer, 10, 0);
printf ("Received World %d\n", request_nbr);
}
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
C. ROUTER -DEALER模式
server端:
qyhzmqserverworker.h:
#ifndef QYHZMQSERVERWORKER_H
#define QYHZMQSERVERWORKER_H
#include
class QyhZmqServerWorker
{
public:
QyhZmqServerWorker(void *ctx);
void work();
private:
zmq::context_t *ctx_;
zmq::socket_t worker_;
};
#endif // QYHZMQSERVERWORKER_H
qyhzmqserverworker.cpp:
#include "qyhzmqserverworker.h"
QyhZmqServerWorker::QyhZmqServerWorker(void *ctx):
ctx_((zmq::context_t *)ctx),
worker_(*ctx_, ZMQ_REP)
{
}
void QyhZmqServerWorker::work()
{
worker_.connect("inproc://workers");
try {
while (true) {
zmq::message_t msg;
zmq::message_t copied_msg;
worker_.recv(&msg);
//处理结尾没有\0的问题
printf("recv:%s\n",std::string((char*)msg.data(),msg.size()).c_str());
copied_msg.copy(&msg);
worker_.send(copied_msg);
}
}
catch (std::exception &e) {}
}
qyhzmqserver.h:
#ifndef QYHZMQSERVER_H
#define QYHZMQSERVER_H
#include
#include
#include
#include
#include
class QyhZmqServer
{
public:
QyhZmqServer();
//线程数量
enum{ MAX_THREAD = 10 };
//线程中初始化的入口
void run();
private:
zmq::context_t ctx_;
zmq::socket_t frontend_;
zmq::socket_t backend_;
};
#endif // QYHZMQSERVER_H
qyhzmqserver.cpp:
#include "qyhzmqserver.h"
#include "qyhzmqserverworker.h"
QyhZmqServer::QyhZmqServer():
ctx_(1),
frontend_(ctx_, ZMQ_ROUTER),
backend_(ctx_, ZMQ_DEALER)
{
}
void QyhZmqServer::run()
{
frontend_.bind("tcp://*:5555");
backend_.bind("inproc://workers");
std::vector
std::vector
for (int i = 0; i < MAX_THREAD; ++i)
{
//一个新的工人
worker.push_back(new QyhZmqServerWorker((void *)&ctx_));
//启动一个线程,执行这个工人的 work函数
worker_thread.push_back(new std::thread(std::bind(&QyhZmqServerWorker::work, worker[i])));
worker_thread[i]->detach();
}
//执行代理操作
try {
zmq::proxy(frontend_, backend_, nullptr);
}
catch (std::exception &e) {}
for (int i = 0; i < MAX_THREAD; ++i) {
delete worker[i];
delete worker_thread[i];
}
}
main.cpp:
#include "qyhzmqserver.h"
int main(int argc, char *argv[])
{
QyhZmqServer server;
std::thread t(std::bind(&QyhZmqServer::run, &server));
t.detach();
getchar();
return 0;
}
CLIENT端:
main.cpp:
#include
#include
#include
#include
#include
#include "zhelpers.hpp"
class client_task {
public:
client_task()
: ctx_(1),
client_socket_(ctx_, ZMQ_REQ)
{}
void start() {
client_socket_.connect("tcp://localhost:5555");
int timeout = 1000;
zmq_setsockopt (client_socket_, ZMQ_RCVTIMEO, &timeout, sizeof(timeout));
zmq_setsockopt (client_socket_, ZMQ_SNDTIMEO, &timeout, sizeof(timeout));
int request_nbr = 0;
//这里出现异常,就直接退出了线程!
try {
while (true) {
std::stringstream ss;
ss<<"request :"<< ++request_nbr;
std::string data = ss.str();
zmq::message_t s(data.c_str(),data.length());
client_socket_.send(s);
zmq::message_t m;
client_socket_.recv(&m);
printf("recv:%s\n",std::string((char *)m.data(),m.size()).c_str());
Sleep(1000);
}
}
catch (std::exception &e) {}
}
private:
zmq::context_t ctx_;
zmq::socket_t client_socket_;
};
int main (void)
{
client_task ct1;
client_task ct2;
client_task ct3;
std::thread(std::bind(&client_task::start, &ct1)).detach();
std::thread(std::bind(&client_task::start, &ct2)).detach();
std::thread(std::bind(&client_task::start, &ct3)).detach();
getchar();
return 0;
}
对subscriber的简单封装,以供大家参考。解决了多线程调用的问题,并且可以自由 开始停止。实现了优雅的启动停止。
qyhzmqsubscriber.h
#ifndef QYHZMQSUBSCRIBER_H
#define QYHZMQSUBSCRIBER_H
#include
#include
#include
class QyhZmqSubscriber
{
public:
//回调绑定
typedef std::function
QyhZmqSubscriber(const std::string _url, QyhZmqSubscriberCallback _subcallback);
~QyhZmqSubscriber();
//开始订阅
void start();
//停止订阅
void stop();
private:
void messageloop();
static void messagethread(void *arg);
private:
volatile bool isStop;
std::thread msgThread;
zmq::context_t* context;
zmq::socket_t* subscriber;
std::string url;
QyhZmqSubscriberCallback subcallback;
};
#endif // QYHZMQSUBSCRIBER_H
qyhzmqsubscriber.cpp
#include "qyhzmqsubscriber.h"
#include "global.h"
QyhZmqSubscriber::QyhZmqSubscriber(const std::string _url, QyhZmqSubscriberCallback _subcallback):
url(_url),
subcallback(_subcallback),
isStop(true),
context(NULL)
{
}
QyhZmqSubscriber::~QyhZmqSubscriber()
{
stop();
}
//开始订阅
void QyhZmqSubscriber::start()
{
if(!isStop)return ;//运行中
isStop=false;
msgThread = std::thread(&QyhZmqSubscriber::messagethread, this);
}
//停止订阅
void QyhZmqSubscriber::stop()
{
if(isStop)return ;//已停止
isStop = true;
delete context;
if(msgThread.joinable())
msgThread.join();
}
void QyhZmqSubscriber::messagethread(void *arg)
{
((QyhZmqSubscriber *)arg)->messageloop();
}
void QyhZmqSubscriber::messageloop()
{
//非停止订阅的状态
context = new zmq::context_t(1);
subscriber = new zmq::socket_t(*context,ZMQ_SUB);
subscriber->connect(url);
subscriber->setsockopt(ZMQ_SUBSCRIBE, "", 0);
while(!isStop)
{
zmq::message_t message;
try{
subscriber->recv(&message);
}catch(std::exception& e){
//被终止时,会抛出异常
}
if(isStop)break;
std::string str = std::string(static_cast
if(subcallback==nullptr){
continue;
}else{
subcallback(str);
}
}
delete subscriber;
}
main.cpp
#include
#include "qyhzmqsubscriber.h"
class LogSubscriber
{
public:
LogSubscriber():sub(NULL)
{
}
~LogSubscriber()
{
if(sub){
delete sub;
sub = NULL;
}
}
void init()
{
if(sub)
{
delete sub;
sub = NULL;
}
//配置参数
std::string url = "tcp://localhost:5555";
QyhZmqSubscriber::QyhZmqSubscriberCallback subcallback = std::bind(&LogSubscriber::onSub, this, std::placeholders::_1);
sub = new QyhZmqSubscriber(url,subcallback);
}
void startSub()
{
sub->start();
}
void stopSub()
{
sub->stop();
}
private:
void onSub(std::string msg)
{
//your msg process
std::cout<
private:
QyhZmqSubscriber *sub;
};
int main(int argc, char const *argv[])
{
LogSubscriber logsub;
logsub.init();
bool quit = false;
while(!quit){
char c;
std::cin>>c;
switch(c){
case 's':logsub.startSub();break;
case 't':logsub.stopSub();break;
case 'q':quit=true;break;
}
}
return 0;
}
运行结果截图
---------------------
作者:jsqinyinghao
来源:CSDN
原文:https://blog.csdn.net/qinyinghao/article/details/79000977?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!