1.前言
最近一直在学习ZeroMQ的一些东东,越学越感觉ZeroMQ太强大了,索性自己也私下开始安排做些关于ZeroMQ的东西,只有这样才能够真正的体会到ZeroMQ的精髓,话不多说了,从今天开始准备每天或每两天写一个简单的ZeroMQ的小实例,也希望通过这些简单的小实例能够强化一些ZeroMQ理论知识,这个实例是我之前在大学时为了课程设计写过的课题报告,当时是做一个字符界面的聊天室,当时自己也是折腾的好久,这个Socket函数以及I/O事件的处理,于是我就随手选了它,看看用ZeroMQ来实现一个字符界面的聊天室到底有多简单,我选用的模式服务器端开启PULL模式和PUB的端口,而客户端开启的是PUSH模式和SUB的端口,话不多说,直接上代码
2. 服务器端代码
#include
#include
#include
#include
#include
#include
#define NAME_SIZE 64
#define BUFFER_SIZE 1024
int main(int argc,char** argv)
{
if(argc < 3)
{
printf("syntax:%s \n",argv[0]);
exit(EXIT_SUCCESS);
}
void* context = zmq_init(1);
assert(context);
void* receiver = zmq_socket(context,ZMQ_PULL);
void* publiser = zmq_socket(context,ZMQ_PUB);
zmq_bind(receiver,argv[1]);
zmq_bind(publiser,argv[2]);
while(true)
{
zmq_msg_t msg;
zmq_pollitem_t items[] =
{
{receiver,0,ZMQ_POLLIN,0}
};
int rc = zmq_poll(items,1,-1);
if(rc == -1)
break;
if(items[0].revents & ZMQ_POLLIN)
{
char receBuffer[BUFFER_SIZE];
memset(receBuffer,0,sizeof(receBuffer));
zmq_msg_init(&msg);
zmq_msg_recv(&msg,receiver,0);
memcpy(receBuffer,(char*)zmq_msg_data(&msg),zmq_msg_size(&msg
zmq_msg_close(&msg);
printf("MSG:%s\n",receBuffer);
zmq_msg_init_size(&msg,strlen(receBuffer));
memcpy((char*)zmq_msg_data(&msg),receBuffer,strlen(receBuffer
zmq_msg_send(&msg,publiser,0);
zmq_msg_close(&msg);
}
}
zmq_close(publiser);
zmq_close(receiver);
zmq_ctx_destroy(context);
return true;
}
3.客户端代码
#include
#include
#include
#include
#include
#include
#include
#define NAME_SIZE 64
#define BUFFER_SIZE 1024
struct worker_t
{
worker_t()
{
context = NULL;
endpoint = NULL;
}
void* context;
char* endpoint;
};
void* worker(void* argv)
{
assert(argv);
worker_t* worker = (worker_t*)argv;
void* receiver = zmq_socket(worker->context,ZMQ_SUB);
zmq_setsockopt(receiver,ZMQ_SUBSCRIBE,"",0);
zmq_connect(receiver,worker->endpoint);
zmq_pollitem_t items[] =
{
{receiver,0,ZMQ_POLLIN,0}
};
while(true)
{
char buffer[BUFFER_SIZE];
memset(buffer,0,sizeof(buffer));
int rc = zmq_poll(items,1,-1);
if(rc==-1)
break;
if(items[0].revents & ZMQ_POLLIN)
{
zmq_msg_t reply;
zmq_msg_init(&reply);
zmq_msg_recv(&reply,receiver,0);
int size = zmq_msg_size(&reply);
size = (size > NAME_SIZE)? NAME_SIZE-2 : size;
memcpy(buffer,(char*)zmq_msg_data(&reply),size);
buffer[size+1] = 0;
zmq_msg_close(&reply);
printf("%s\n",buffer);
}
}
zmq_close(receiver);
return NULL;
}
int main(int argc,char** argv)
{
if(argc < 4)
{
printf("syntax:%s \n",argv[0]);
exit(EXIT_SUCCESS);
}
void* context = zmq_init(1);
void* sender = zmq_socket(context,ZMQ_PUSH);
zmq_connect(sender,argv[2]);
worker_t arg;
arg.context = context;
arg.endpoint = argv[3];
pthread_t work;
pthread_create(&work,NULL,worker,&arg);
while(true)
{
char buffer[BUFFER_SIZE];
char content[BUFFER_SIZE];
memset(buffer,0,sizeof(buffer));
memset(content,0,sizeof(content));
std::cin.getline(buffer,sizeof(buffer));
if(!strcmp(buffer,"quit"))
break;
sprintf(content,"%s:%s",argv[1],buffer);
zmq_msg_t msg;
zmq_msg_init_size(&msg,strlen(content));
memcpy((char*)zmq_msg_data(&msg),content,strlen(content));
zmq_msg_send(&msg,sender,0);
zmq_msg_close(&msg);
}
zmq_close(&sender);
zmq_term(context);
return 0;
}
4. 总结
这个实例通过ZeroMQ来实现的话,只需要短短的几十行代码即可完成,而如果采用传统的Socket编程的话,估计至少需要上百行的代码吧,再次被ZeroMQ所折服,这也是我想要学习ZeroMQ的原因,也希望那些想要从事服务器端开发的道友能够从ZeroMQ中找到惊喜,谢谢