zmq router and dealer

/************************************************************************* 
 *      > File Name: ZMQ_PipeSocket.h  
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07 
 *      > statement: ZMQ封装类 
 *************************************************************************/  
#ifndef ZMQ_PIPE_SOCKET_H  
#define ZMQ_PIPE_SOCKET_H  
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <assert.h>  
#include <string.h>  
#include <stdint.h>
#include <zmq.h>  
#include <string>  
#include <set>
namespace zmqpipe  
{  
using namespace std;  
class ZMQ_PIPESocket   
{  
private:  
    void *m_pContext;  
    void *m_pSocket;  
    int m_nSocketType;  
    string m_strSendServer;                 // 发送的服务器地址  
public:  
    ZMQ_PIPESocket();  
    ~ZMQ_PIPESocket();  
    /* 
     * @brief 初始化zmq 
     * */  
    bool Init(int SocketType, const string &addr, int sendhwm = 1000, int recvhwm = 1000, int sendtimeout = 1000);  
    /* 
     * @brief 发送info指向的对象  
     * @len 对象的大小 字节数 
     * @return 发送成功返回true 
     * */  
    bool Send(void *info, int len);  
    /* 
     * @brief 发送string对象  
     * @return 发送成功返回true 
     * */  
    bool Send(const string &strSend);  

    /* 
     * @brief 接收数据 接收的数据由info指向 
     * @return 接收成功返回true 
     * */  
    bool Recv(void *info);  
    /* 
     * @brief 接收string对象数据 
     * @return 接收成功返回true 
     * */  
    bool Recv(string &strRecv);  
    /* 
     * @brief 获取发送服务器地址 
     * */  
    inline void GetSendAddr(string &strOut)   
    {  
        strOut = m_strSendServer;  
    }
	/*
	 * @brief recieving from a socket is over
	 * */
	bool RecvOver();
};  
}  
  
#endif  
/************************************************************************* 
 *      > File Name: ZMQ_PipeSocket.cpp 
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07
 *      > statement: ZMQ封装类 
 *************************************************************************/  
#include "ZMQ_PipeSocket.h"  
namespace zmqpipe  
{  
ZMQ_PIPESocket::ZMQ_PIPESocket()   
{  
    m_pContext = NULL;  
    m_pSocket = NULL;  
}  
bool ZMQ_PIPESocket::Init(int SocketType, 
						  const string &addr, 
						  int sendhwm, 
						  int recvhwm, 
						  int sendtimeout)   
{  
    m_pContext = zmq_ctx_new();  
    if(!m_pContext) return false;  
    m_pSocket = zmq_socket(m_pContext, SocketType);  
    if(!m_pSocket) return false;  
	int rc;
	switch(SocketType)
	{
//	case ZMQ_REP:
	case ZMQ_PULL:
	case ZMQ_PUB:
		rc = zmq_bind(this->m_pSocket, addr.c_str());
		break;
	case ZMQ_REP:
	case ZMQ_REQ:
	case ZMQ_PUSH:
	case ZMQ_SUB:
		rc = zmq_connect(this->m_pSocket, addr.c_str());
		break;
	default:
		return false;
	}
    rc = zmq_setsockopt(m_pSocket, ZMQ_SNDHWM, &sendhwm, sizeof(sendhwm));  
    if(rc) return false;  
    rc = zmq_setsockopt(m_pSocket, ZMQ_RCVHWM, &recvhwm, sizeof(recvhwm));  
    if(rc) return false;  
    rc = zmq_setsockopt(m_pSocket, ZMQ_SNDTIMEO, &sendtimeout, sizeof(sendtimeout));  
    if(rc) return false;  
    m_strSendServer = addr;  
  
    return true;  
}  
/* 
 * @brief 发送info指向的对象  
 * @len 对象的大小 字节数 
 * */  
bool ZMQ_PIPESocket::Send(void *info, int len)   
{  
    int rc;  
    zmq_msg_t msg;  
    rc = zmq_msg_init_size(&msg, len);  
    if(rc) return false;  
    memcpy(zmq_msg_data(&msg), (char *)info, len);  
    rc = zmq_msg_send(&msg, this->m_pSocket, 0);  
  
    return rc == len;  
}  
/* 
 * @brief 发送string对象  
 * */  
bool ZMQ_PIPESocket::Send(const string &strSend)   
{  
    int rc;  
    size_t len = strSend.size();  
    zmq_msg_t msg;  
    rc = zmq_msg_init_size(&msg, len);  
    if(rc) return false;  
    memcpy(zmq_msg_data(&msg), strSend.c_str(), len);  
    size_t Len = zmq_msg_send(&msg, this->m_pSocket, 0);  
  
    return Len == len;  
}  
/* 
 * @brief 接收数据 接收的数据由info指向 
 * */  
bool ZMQ_PIPESocket::Recv(void *info)   
{  
    int rc;  
    zmq_msg_t msg;  
    rc = zmq_msg_init(&msg);  
    if(rc) return false;  
    int len = zmq_msg_recv(&msg, this->m_pSocket, 0);    // 阻塞方式  
    if(len <= 0) return false;  
    memcpy(info, (char *)zmq_msg_data(&msg), len);  
    if(zmq_msg_close(&msg)) return false;  
  
    return true;  
}     
/* 
 * @brief 接收string对象数据 
 * */  
bool ZMQ_PIPESocket::Recv(string &strRecv)   
{  
    int rc;  
    zmq_msg_t msg;  
    rc = zmq_msg_init(&msg);  
    if(rc) return false;  
    int len = zmq_msg_recv(&msg, this->m_pSocket, 0);    // 阻塞方式  
    if(len <= 0) return false;  
    strRecv.assign((char *)zmq_msg_data(&msg), len);  
    if(zmq_msg_close(&msg)) return false;  
  
    return true;  
}     
/*
 * @brief recieving from a socket is over
 * */
bool ZMQ_PIPESocket::RecvOver()
{
	int64_t more;
	size_t more_size = sizeof(more);
	zmq_getsockopt(m_pSocket, ZMQ_RCVMORE, &more, &more_size);

	return more <= 0;
}
ZMQ_PIPESocket::~ZMQ_PIPESocket()   
{  
    if(m_pSocket)   
    {  
        zmq_close(m_pSocket);  
        m_pSocket = NULL;  
    }  
    if(m_pContext)   
    {  
        zmq_ctx_destroy(m_pContext);  
        m_pContext = NULL;  
    }  
}  
}  
/************************************************************************* 
 *      > File Name: ZMQ_Poll.h  
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07 
 *      > statement: zmq poll for selecting zmq socket
 *************************************************************************/  
#ifndef ZMQ_POLL_H  
#define ZMQ_POLL_H  
#include <stdio.h>  
#include <zmq.h>  
#include <vector>
namespace zmqpoll
{  
static const int MAXPOLLNUM = 1024;
using namespace std;
class ZMQ_Poll
{  
private:  
	vector<zmq_pollitem_t>m_vecPollItems;
	vector<bool>m_vecExisted;
	int m_nMaxIndex;
public:
	/*
	 * @brief constructor:initialize m_vecPollItems
	 * */
	ZMQ_Poll() 
	{
		m_vecPollItems.resize(MAXPOLLNUM);
		m_vecExisted.resize(MAXPOLLNUM);
		m_nMaxIndex = -1;
	}
	/*
	 * @brief add a zmq socket into the poll
	 * @psocket socket ptr
	 * @id the identifier for the zmq object
	 * @events the poll events
	 * @return true if adding is ok
	 * */
	bool AddPoll(void *psocket, int id, short events);
	/*
	 * @brief the poll events happen
	 * @return true if happen
	 * */
	inline bool IsPollComing(int id, short events)
	{
		return m_vecPollItems[id].revents & events;
	}
	/*
	 * @brief to poll the events
	 * @return >= 0 is ok -1 error
	 * */
	inline int Poll(long timeout)
	{
		return zmq_poll(&m_vecPollItems[0], m_nMaxIndex + 1, timeout);
	}
};  
}  
  
#endif  
/************************************************************************* 
 *      > File Name: ZMQ_Poll.cpp
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07 
 *      > statement: zmq poll for selecting zmq socket
 *************************************************************************/  
#include "ZMQ_Poll.h"
namespace zmqpoll
{  
/*
 * @brief add a zmq socket into the poll
 * @zmq_pipesocket zmq object
 * @id the identifier for the zmq object
 * @events the poll events
 * @return true if adding is ok
 * */
bool ZMQ_Poll::AddPoll(void *psocket, int id, short events)
{
	// validate the entry and the existence
	if(id < 0 && id >= MAXPOLLNUM) return false;
	if(m_vecExisted[id]) return false;
	if(id > m_nMaxIndex) m_nMaxIndex = id;
	// add into the poll
	zmq_pollitem_t pollitem = {0};
	pollitem.socket = psocket;
	pollitem.events = events;
	m_vecPollItems[id] = pollitem;
	m_vecExisted[id] = true;

	return true;
}
}  
/************************************************************************* 
 *      > File Name: ZMQ_Agent.h  
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07 
 *      > statement: zmq agent
 *************************************************************************/  
#ifndef ZMQ_AGENT_H  
#define ZMQ_AGENT_H  
#include <stdint.h>
#include <string>
#include "ZMQ_Poll.h"
namespace zmqagent
{  
using namespace zmqpoll;
enum AGENTID
{
	FRONT,
	BACK
};
class ZMQ_Agent
{  
private:  
	void *m_pContext;
	void *m_pfrontend;
	void *m_pbackend;
	ZMQ_Poll m_ZmqAgent;
public:
	/*
	 * @brief constructor:
	 * */
	ZMQ_Agent()
	{
		m_pContext = nullptr;
		m_pfrontend = nullptr;
		m_pbackend = nullptr;
	}
	/*
	 * @brief destructor:
	 * */
	~ZMQ_Agent()
	{
		if(m_pfrontend) zmq_close(m_pfrontend);
		if(m_pbackend) zmq_close(m_pbackend);
		if(m_pContext) zmq_ctx_destroy(m_pContext);
	}
	/*
	 * @brief constructor:initialize context and socket
	 * @return true if init is ok
	 * */
	bool Init(int frontend_port, int backend_port); 
	/*
	 * @brief whether front end can receive data
	 * @return true if yes
	 * */
	int Poll();
	/*
	 * @brief whether front end can receive data
	 * @return true if yes
	 * */
	bool IsFrontReadyRecv();
	/*
	 * @brief whether back end can receive data
	 * @return true if yes
	 * */
	bool IsBackReadyRecv();
	/*
	 * @brief receive data from clients and send to the back end
	 * @return true is recv is over
	 * */
	bool FrontDeal();
	/*
	 * @brief receive data from the front and send to the front end
	 * @return true is recv is over
	 * */
	bool BackDeal();
};  
}  
  
#endif  
/************************************************************************* 
 *      > File Name: ZMQ_Agent.cpp
 *      > Author: wangzhicheng 
 *      > Mail: 2363702560@qq.com 
 *      > Created Time: 2017-02-07 
 *      > statement: zmq agent
 *************************************************************************/  
#include "ZMQ_Agent.h"
namespace zmqagent
{  
/*
 * @brief constructor:initialize context and socket
 * @return true if init is ok
 * */
bool ZMQ_Agent::Init(int frontend_port, int backend_port)
{
	// new context and socket
	m_pContext = zmq_ctx_new();
	if(!m_pContext) return false;
	m_pfrontend = zmq_socket(m_pContext, ZMQ_ROUTER);
	m_pbackend = zmq_socket(m_pContext, ZMQ_DEALER);
	if(!m_pfrontend || !m_pbackend) return false;
	// bind 
	char buf[64];
	const static string comm = "tcp://*:";
	string addr;
	if(frontend_port < 0 || frontend_port >= 65535) return false;
	if(backend_port < 0 || backend_port >= 65535) return false;
	snprintf(buf, sizeof buf, "%d", frontend_port);
	addr = comm;
	addr += buf;
	if(zmq_bind(m_pfrontend, addr.c_str())) return false;
	snprintf(buf, sizeof buf, "%d", backend_port);
	addr = comm;
	addr += buf;
	if(zmq_bind(m_pbackend, addr.c_str())) return false;
	// add into poll
	m_ZmqAgent.AddPoll(m_pfrontend, FRONT, ZMQ_POLLIN);
	m_ZmqAgent.AddPoll(m_pbackend, BACK, ZMQ_POLLIN);

	return true;
}
/*
 * @brief whether front end can receive data
 * @return true if yes
 * */
int ZMQ_Agent::Poll()
{
	return m_ZmqAgent.Poll(-1);
}
/*
 * @brief whether front end can receive data
 * @return true if yes
 * */
bool ZMQ_Agent::IsFrontReadyRecv()
{
	return m_ZmqAgent.IsPollComing(FRONT, ZMQ_POLLIN);
}
/*
 * @brief whether back end can receive data
 * @return true if yes
 * */
bool ZMQ_Agent::IsBackReadyRecv()
{
	return m_ZmqAgent.IsPollComing(BACK, ZMQ_POLLIN);
}
/*
 * @brief receive data from clients and send to the back end
 * @return true is recv is over
 * */
bool ZMQ_Agent::FrontDeal()
{
	int64_t more;
	size_t more_size = sizeof(more);
	zmq_msg_t message;
	zmq_msg_init(&message);
	zmq_msg_recv(&message, m_pfrontend, 0);
    zmq_getsockopt(m_pfrontend, ZMQ_RCVMORE, &more, &more_size);
	zmq_msg_send(&message, m_pbackend, more ? ZMQ_SNDMORE : 0);
	zmq_msg_close(&message);

	if(!more) return true;
	else return false;
}
/*
 * @brief receive data from the front and send to the front end
 * @return true is recv is over
 * */
bool ZMQ_Agent::BackDeal()
{
	int64_t more;
	size_t more_size = sizeof(more);
	zmq_msg_t message;
	zmq_msg_init(&message);
	zmq_msg_recv(&message, m_pbackend, 0);
    zmq_getsockopt(m_pbackend, ZMQ_RCVMORE, &more, &more_size);
	zmq_msg_send(&message, m_pfrontend, more ? ZMQ_SNDMORE : 0);
	zmq_msg_close(&message);

	if(!more) return true;
	else return false;
}
}  
  
/************************************************************************* 
    > File Name: test.cpp 
    > Author: wangzhicheng 
    > Mail: 2363702560@qq.com  
    > Created Time:2017-02-07
 ************************************************************************/  
#include <iostream>  
#include <vector>  
#include <thread>  
#include <chrono>  
#include "ZMQ_PipeSocket.h"  
//#include "ZMQ_Poll.h"  
#include "ZMQ_Agent.h"
using namespace zmqpipe;  
using namespace zmqagent;  
static const string ADDR0 = "tcp://127.0.0.1:8888";  
static const string ADDR1 = "tcp://127.0.0.1:9999";  
static const string ADDR2 = "tcp://*:8888";  
static const string ADDR3 = "tcp://*:9999";  
static const chrono::milliseconds dura(1000);  // 1s
void client_thread()
{
	string str;
    ZMQ_PIPESocket sender;  
    if(!sender.Init(ZMQ_REQ, ADDR0, false))  
    {  
        cerr << "client init failed...!" << endl;  
        exit(EXIT_FAILURE);  
	}
    while(1)  
    {  
        if(!sender.Send("Hello World...!"))  
        {  
            cerr << "client send failed...!" << endl;  
		}
        if(!sender.Recv(str))  
        {  
            cerr << "client recv failed...!" << endl;  
		}
		else cout << "client recv = " << str << endl;
	    this_thread::sleep_for(dura);  
	}

}
void server_thread()  
{  
    string str;  
    ZMQ_PIPESocket receiver;  
    if(!receiver.Init(ZMQ_REP, ADDR1, false))  
    {  
        cerr << "server init failed...!" << endl;  
        exit(EXIT_FAILURE);  
    }  
    while(1)  
    {  
        if(!receiver.Recv(str))  
        {  
            cerr << "server recv failed...!" << endl;  
        }  
		else cout << "server recv = " << str << endl;
	    this_thread::sleep_for(dura);  
        if(!receiver.Send("Hello World...!"))  
        {  
            cerr << "server send failed...!" << endl;  
		}
    }  
}  
void agent_thread()
{
	ZMQ_Agent agent;
	if(!agent.Init(8888, 9999)) 
	{
		cerr << "agent init failed...!" << endl;
		exit(EXIT_FAILURE);
	}
	while(1)
	{
		int rc = agent.Poll();
		if(rc < 0) 
		{
			cerr << "zmq poll error...!" << endl;
			break;
		}
		else
		if(!rc)
		{
			cout << "no poll event happens...!" << endl;
			continue;
		}
		if(agent.IsFrontReadyRecv())
		{
			while(1)
			{
				if(agent.FrontDeal()) break;
			}
		}
		if(agent.IsBackReadyRecv())
		{
			while(1)
			{
				if(agent.BackDeal()) break;
			}
		}
	}
}
int main()  
{  
    thread th_client(client_thread);  
    thread th_server(server_thread);  
    thread th_agent(agent_thread);  
	th_client.join();  
	th_server.join();  
	th_agent.join();  
  
    return 0;  
}  
CC=g++  
all:  
	$(CC) -std=c++11 -g -o TestAgent  test.cpp ZMQ_PipeSocket.h ZMQ_PipeSocket.cpp ZMQ_Poll.h ZMQ_Poll.cpp ZMQ_Agent.h ZMQ_Agent.cpp -lzmq -pthread 

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值