/********************************************************************
author : Clark/陈泽丹
created : 2014-6-21
purpose : ZMQ辅助类
*********************************************************************/
#pragma once
#include
//ZMQ设备上下文
//注意不要通过引用使用它,否则浅拷贝时会导致引用量在析构时释放了设备上下文
class ZmqContext
{
public:
static void Start( long _io_thread_num = 1 );
static void Stop();
static void* GetContext();
private:
ZmqContext( long _io_thread_num );
~ZmqContext();
private:
static ZmqContext* mp_zmqcontext;
void* context;
};
//ZMQ套接字
//注意必须先行统一初始化的建立节点,不然不会保存发送接收的信息缓存
//当节点初始化不统一时,发送的信息不会缓存起来,然后导致recv时在那挂起
//所以recv的节点一定要预先建好
class ZmqSkt
{
public:
ZmqSkt( const char* _addrest );
~ZmqSkt();
void Close();
void* GetContext(){ return skt; }
protected:
char addr[256];
void* skt;
};
//ZMQ_PAIR(只能1:1)
struct PairSkt: public ZmqSkt
{
PairSkt( const char* _addrest ):ZmqSkt(_addrest){}
long Recv( char* _buf, long _len );
void Send( char* _buf, long _len );
};
struct ConnetPairSkt: public PairSkt
{
ConnetPairSkt( const char* _addrest/* = "inproc://unknown"*/ );
};
struct BindPairSkt: public PairSkt
{
BindPairSkt( const char* _addrest/* = "inproc://unknown"*/ );
};
//ZMQ_PUSH & ZMQ_PULL (N:1)
struct PushPairSkt: public ZmqSkt
{
PushPairSkt( const char* _addrest/* = "inproc://unknown"*/ );
void Send( char* _buf, long _len );
};
struct PullPairSkt: public ZmqSkt
{
PullPairSkt( const char* _addrest/* = "inproc://unknown"*/ );
long Recv( char* _buf, long _len );
};
//ZMQ_REQ & ZMQ_REP
struct ReqSkt: public ZmqSkt
{
ReqSkt( const char* _addrest/* = "inproc://unknown"*/ );
void BeginSend( char* _buf, long _len );
long End( char* _buf, long _len );
void End();
};
struct RepSkt: public ZmqSkt
{
RepSkt( const char* _addrest/* = "inproc://unknown"*/ );
long BeginRecv( char* _buf, long _len );
void End( char* _buf = "OK", long _len = 2 );
};
class PollItem
{
public:
PollItem();
virtual ~PollItem();
void Init( std::vector< ZmqSkt* >* _skt );
void Uninit();
void WaitEvents();
virtual bool OnSktEvent( long _skt_id ) = 0;
private:
void* mp_poll_item;
long len;
};
#include "ZmqHelpler.h"
#include
#include
void api_zmq_send( void* _skt, char* _buf, long _len );
long api_zmq_recv( void* _skt, char* _buf, long _len );
void api_zmq_send( void* _skt, char* _buf, long _len )
{
zmq_msg_t msg;
zmq_msg_init_size(&msg, _len);
memcpy( zmq_msg_data(&msg), _buf, _len);
zmq_sendmsg(_skt, &msg, ZMQ_DONTWAIT);
zmq_msg_close(&msg);
}
long api_zmq_recv( void* _skt, char* _buf, long _len )
{
zmq_msg_t msg;
zmq_msg_init(&msg);
zmq_recvmsg(_skt,&msg,0);
long num = 0;
if( _len >= zmq_msg_size(&msg) )
{
num = zmq_msg_size(&msg);
memcpy(_buf,(char*)zmq_msg_data(&msg),num);
}
zmq_msg_close(&msg);
return num;
}
//ZMQ设备上下文
//注意不要通过引用使用它,否则浅拷贝时会导致引用量在析构时释放了设备上下文
ZmqContext* ZmqContext::mp_zmqcontext = 0;
void ZmqContext::Start( long _io_thread_num )
{
if( 0 == mp_zmqcontext )
{
mp_zmqcontext = new ZmqContext(_io_thread_num);
}
}
void ZmqContext::Stop()
{
if( 0 != mp_zmqcontext )
{
delete mp_zmqcontext;
mp_zmqcontext = 0;
}
}
void* ZmqContext::GetContext()
{
if( 0 != mp_zmqcontext )
return mp_zmqcontext->context;
return 0;
}
ZmqContext::ZmqContext( long _io_thread_num )
{
context = zmq_init(_io_thread_num);
}
ZmqContext::~ZmqContext()
{
zmq_term(context);
}
//ZMQ套接字
long G_ZMQ_COUNT = 0;
ZmqSkt::ZmqSkt(const char* _addrest)
{
//strcpy( addr, _addrest );
//G_ZMQ_COUNT = G_ZMQ_COUNT + 1;
//printf("G_ZMQ_COUNT %s %d \n", addr, G_ZMQ_COUNT);
}
ZmqSkt::~ZmqSkt()
{
//G_ZMQ_COUNT = G_ZMQ_COUNT - 1;
//printf("G_ZMQ_COUNT %s %d \n", addr, G_ZMQ_COUNT);
Close();
}
void ZmqSkt::Close()
{
zmq_close(skt);
}
//ZMQ_PAIR(只能1:1)
long PairSkt::Recv( char* _buf, long _len )
{
return api_zmq_recv( skt, _buf, _len );
}
void PairSkt::Send( char* _buf, long _len )
{
api_zmq_send( skt, _buf, _len );
}
ConnetPairSkt::ConnetPairSkt( const char* _addrest ):PairSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_PAIR );
zmq_connect( skt, _addrest );
}
BindPairSkt::BindPairSkt( const char* _addrest ):PairSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_PAIR );
zmq_bind( skt, _addrest );
}
//ZMQ_PUSH & ZMQ_PULL (N:1)
PushPairSkt::PushPairSkt( const char* _addrest ):ZmqSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_PUSH );
zmq_connect( skt, _addrest );
}
void PushPairSkt::Send( char* _buf, long _len )
{
api_zmq_send(skt,_buf,_len);
}
PullPairSkt::PullPairSkt( const char* _addrest ):ZmqSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_PULL );
zmq_bind( skt, _addrest );
}
long PullPairSkt::Recv( char* _buf, long _len )
{
return api_zmq_recv( skt, _buf, _len );
}
//ZMQ_REQ & ZMQ_REP
ReqSkt::ReqSkt( const char* _addrest ):ZmqSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_REQ );
zmq_connect( skt, _addrest );
}
void ReqSkt::BeginSend( char* _buf, long _len )
{
api_zmq_send( skt, _buf, _len );
}
long ReqSkt::End( char* _buf, long _len )
{
return api_zmq_recv( skt, _buf, _len );
}
void ReqSkt::End()
{
char msg[64];
api_zmq_recv(skt, msg, sizeof(msg));
}
RepSkt::RepSkt( const char* _addrest ):ZmqSkt(_addrest)
{
skt = zmq_socket( ZmqContext::GetContext(), ZMQ_REP );
zmq_bind( skt, _addrest );
}
long RepSkt::BeginRecv( char* _buf, long _len )
{
return api_zmq_recv( skt, _buf, _len );
}
void RepSkt::End( char* _buf, long _len )
{
api_zmq_send( skt, _buf, _len );
}
PollItem::PollItem( ):mp_poll_item(0),len(0)
{
}
PollItem::~PollItem( )
{
Uninit();
}
void PollItem::Init(std::vector< ZmqSkt* >* _skt )
{
if( NULL == _skt)
return;
Uninit();
len = _skt->size();
zmq_pollitem_t *p_items = new zmq_pollitem_t[_skt->size()];
for( int i=0; i<_skt->size(); ++i )
{
p_items[i].socket = (*_skt)[i]->GetContext();
p_items[i].fd = 0;
p_items[i].events = ZMQ_POLLIN;
}
mp_poll_item = p_items;
}
void PollItem::Uninit()
{
if( 0 != mp_poll_item )
{
zmq_pollitem_t **p_items = (zmq_pollitem_t **)mp_poll_item;
delete[] p_items;
mp_poll_item = 0;
}
}
void PollItem::WaitEvents()
{
bool is_run = true;
while( is_run )
{
zmq_pollitem_t *p_items = (zmq_pollitem_t *)mp_poll_item;
int nRet = zmq_poll(p_items,len,-1);
if(0 == nRet)
continue;
for( int i=0; i 0 )
{
if( OnSktEvent(i) )
{
is_run = false;
}
}
}
}
}