最近在做服务器,发现zmq的同步收发不是很适合项目需求,这里有一套异步模式的zmq demo分享给大家,仅供参考.
我这里使用的是 代理模式,
1.client 代码 这里使用的.hpp的zmq,发现并不好,建议使用.h的zmq.
#include
#include
#include
#include "czmq.h"
using std::endl;
using std::cout;
using namespace std;
int main()
{
zmq::context_t Context(1);
zmq::socket_t ReqSock(Context, ZMQ_DEALER);
char identity [10];
sprintf (identity, "%04X-%04X", randof (0x10000), randof (0x10000));
ReqSock.setsockopt(ZMQ_IDENTITY,"identity",10);
ReqSock.connect("tcp://localhost:5559");
zmq_pollitem_t items [] = { { ReqSock, 0, ZMQ_POLLIN, 0 } };
int request_nbr = 0;
while (true) {
// Tick once per second, pulling in arriving messages
int centitick;
for (centitick = 0; centitick < 100; centitick++) {
zmq_poll (items, 1, 10 * ZMQ_POLL_MSEC);
if (items [0].revents & ZMQ_POLLIN) {
zmsg_t *msg = zmsg_recv (ReqSock);
zframe_t *cont = zmsg_pop (msg);
if(cont)
{
char* p_cont2 = zframe_strdup(cont);
cout<<"p_cont2:"<
2.server(也就是worker)
void main()
{
void* rspSock = zmq_socket(context, ZMQ_DEALER);
int r = zmq_connect(rspSock, cp->zmqAddr.c_str());
if (r == -1) {
LOG(ERROR) << "zmq_connect failure ";
zmq_close(rspSock);
return;
}
zmq_pollitem_t items[] = { {rspSock, 0, ZMQ_POLLIN, 0} };
while (true) {
int rc = zmq_poll(items, 1, 10 * ZMQ_POLL_MSEC );
if (rc == -1) {
printf ("Error zmq_poll return -1: %s\n", zmq_strerror (errno));
break;
}
if (items [0].revents & ZMQ_POLLIN) {
zmqSender->sendmtx.lock();
zmsg_t *msg = zmsg_recv(rspSock);
zmqSender->sendmtx.unlock();
zframe_t *addr = zmsg_pop(msg);
zframe_t *cont = zmsg_pop(msg);
assert (cont);
///下面的代码段也可以使用zframe_strdup如果使用zframe_strdup()函数,一定要使用free()来释放内存
assert (zframe_is (cont));
size_t size = zframe_size (cont);
char *contstr = (char *) malloc (size + 1);
assert (contstr);
memcpy (contstr, zframe_data (cont), size);
contstr [size] = 0;
//char* contstr = zframe_strdup(cont); //contstr就是解析出来的消息正文内容
if (strlen(contstr) > 0)
{
//处理消息
}
if(contstr)
{
free(contstr);
contstr = nullptr;
}
}
}
}
发送消息时使用收到消息时的addr和cont:
zframe_send(&addr, rspSock, ZFRAME_REUSE + ZFRAME_MORE);
zframe_reset(cont, response.c_str(), msg.response.size()+1);
zframe_send(&cont, rspSock, ZFRAME_REUSE);
sendmtx.unlock();
zframe_destroy(&addr);
zframe_destroy(&cont);
另外要注意的是:zmq socket是线程不安全的,即使加锁也会有问题,详细解决方案参考博主的另一篇文章 https://blog.csdn.net/wushuangge/article/details/89396393
3.router代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
static void create_broker(void* context, const char* front_addr, const char* back_addr);
int main(int argc, char* argv[])
{
int major, minor, patch;
zmq_version(&major, &minor, &patch);
int version = ZMQ_MAKE_VERSION(major, minor, patch);
if (version < ZMQ_VERSION)
{
printf("zmq library expect version %d but get %d.\n", ZMQ_VERSION, version);
return 1;
}
void *context = zmq_ctx_new();
const char* front_addr = "tcp://127.0.0.1:5559";
const char* back_addr = "tcp://127.0.0.1:5560";
// create broker
auto broker = make_shared(create_broker, context, front_addr, back_addr);
if (broker)
{
broker->join();
}
zmq_ctx_destroy(context);
return 0;
}
void create_broker(void* context, const char* front_addr, const char* back_addr)
{
assert(context && front_addr && back_addr);
void* frontend = zmq_socket(context, ZMQ_ROUTER);
void* backend = zmq_socket(context, ZMQ_DEALER);
assert(frontend && backend);
int r = zmq_bind(frontend, front_addr);
if (r!=0)
printf("error:bind failure ,port is used...\n");
r = zmq_bind(backend, back_addr);
if (r!=0)
printf("error:bind failure ,port is used...\n");
printf("broker started...\n");
zmq_proxy(frontend, backend, NULL);
zmq_close(frontend);
zmq_close(backend);
printf("broker[%d] closed...\n", pthread_self());
}