在我们刚接触程序编码的时候,我们要轮询数据有没有发过来,我们最多的可能还是使用while+sleep这样的组合,这对于处理来说是一个效率很低的方法同时还消耗cpu,那么在多线程编程中使用libev+nanomsg会不会提高效率呢。下面实例主要工作如下:A B C 三个线程通过nanomsg通信,A线程作为主线程,控制中枢,B C请求均通过A.那么在实际应用中,比如B模块是接收客户请求并解析发送控制命令的,C模块是负责干活的,A是总控,所有控制命令通过A下发到别的模块,这样维护都很方便。那看下怎么实现的吧。
#include
#include
#include
#include
#include
#include
#include
#include
#include
/***************************************************************************************************
动态库:libev nanomsg
概述:A B C 三个线程通过nanomsg通信,A线程作为主线程,控制中枢,B C请求均通过A.
demo示范:
A为指令处理模块
B为指令接收模块
C为指令执行模块
B -> A 开灯
A -> C 开灯
C : 执行开灯
C -> A OK
A -> B OK
总结:
这只是简单的测试使用例子,你可以通过在这个框架的基础上做更多的功能,对于多线程编程这将是一个不
错的选择.
***************************************************************************************************/
typedef struct {
int n; //nanomsg socket
int s; //nanomsg recieve fd
}nanomsg_info_t;
typedef struct {
nanomsg_info_t ab;
nanomsg_info_t ac;
}Aloop_ctrl_t;
typedef struct {
nanomsg_info_t ba;
}Bloop_ctrl_t;
typedef struct {
nanomsg_info_t ca;
}Cloop_ctrl_t;
/*获取系统时间打印*/
uint32_t print_timenow()
{
time_t now;
struct tm *tm_now;
time(&now);
tm_now = localtime(&now);
uint32_t times = tm_now->tm_hour * 3600 + tm_now->tm_min * 60 + tm_now->tm_sec;
printf("[%02d:%02d:%02d]\r\n", tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
return times;
}
/*****************************************子线程C相关**********************************************/
static void watcher_c_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
void *user_data = ev_userdata(loop);
Cloop_ctrl_t *Cloop_ctrl = (Cloop_ctrl_t *)user_data;
uint8_t *dat = NULL;
uint32_t bytes = nn_recv(Cloop_ctrl->ca.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0) {
return;
}
printf("C:%s (A->C)\r\n", (char *)dat);
nn_freemsg(dat);
//接收成功,发送OK
char *str = "OK";
uint8_t *udata = nn_allocmsg(3, 0);
if (NULL != udata) {
memcpy(udata, str, 3);
nn_send(Cloop_ctrl->ca.n, &udata, NN_MSG, NN_DONTWAIT);
}
}
int C_nanomsg_init(Cloop_ctrl_t *Cloop_ctrl)
{
Cloop_ctrl->ca.n = nn_socket(AF_SP, NN_PAIR);
if (Cloop_ctrl->ca.n < 0) {
return -1;
}
if (nn_connect(Cloop_ctrl->ca.n, "inproc://c2a_loop") < 0) {
return -1;
}
size_t size = sizeof(size_t);
if (nn_getsockopt(Cloop_ctrl->ca.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&Cloop_ctrl->ca.s, &size) < 0) {
return -1;
}
return 0;
}
struct ev_loop* C_loop_init(Cloop_ctrl_t *Cloop_ctrl)
{
static struct ev_io watcher_c;
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop) {
printf("create C loop failed\r\n");
return NULL;
}
ev_io_init (&watcher_c, watcher_c_cb, Cloop_ctrl->ca.s, EV_READ);
ev_io_start (loop, &watcher_c);
return loop;
}
void *C_thread(void *arg)
{
Cloop_ctrl_t Cloop_ctrl;
if (C_nanomsg_init(&Cloop_ctrl) < 0) {
printf("nanomsg init failed\r\n");
return ;
}
struct ev_loop* Cloop = C_loop_init(&Cloop_ctrl);
if (NULL == Cloop) {
printf("Cloop init failed\r\n");
return ;
}
ev_set_userdata(Cloop, &Cloop_ctrl);
ev_run (Cloop, 0);
return ;
}
/*****************************************子线程B相关**********************************************/
static void watcher_b_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
void *user_data = ev_userdata(loop);
Bloop_ctrl_t *Bloop_ctrl = (Bloop_ctrl_t *)user_data;
uint8_t *dat = NULL;
uint32_t bytes = nn_recv(Bloop_ctrl->ba.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0) {
return;
}
printf("B:%s (A->B)\r\n\r\n", (char *)dat);
nn_freemsg(dat);
}
static void watcher_timer_cb (struct ev_loop *loop ,struct ev_timer *w, int revents)
{
static int i = 1;
char send_data[128] = {0};
void *user_data = ev_userdata(loop);
Bloop_ctrl_t *Bloop_ctrl = (Bloop_ctrl_t *)user_data;
sprintf(send_data, "Please turn on LED[%d]", i);
i ++;
int length = strlen(send_data) + 1;
uint8_t *udata = nn_allocmsg(length, 0);
if (NULL != udata) {
memcpy(udata, send_data, length);
nn_send(Bloop_ctrl->ba.n, &udata, NN_MSG, NN_DONTWAIT);
}
//如果定时器不重设,就会默认1秒进入一次回调
w->repeat = 10;
ev_timer_again(loop, w);
}
int B_nanomsg_init(Bloop_ctrl_t *Bloop_ctrl)
{
Bloop_ctrl->ba.n = nn_socket(AF_SP, NN_PAIR);
if (Bloop_ctrl->ba.n < 0) {
return -1;
}
if (nn_connect(Bloop_ctrl->ba.n, "inproc://b2a_loop") < 0) {
return -1;
}
size_t size = sizeof(size_t);
if (nn_getsockopt(Bloop_ctrl->ba.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&Bloop_ctrl->ba.s, &size) < 0) {
return -1;
}
return 0;
}
struct ev_loop* B_loop_init(Bloop_ctrl_t *Bloop_ctrl)
{
static struct ev_io watcher_b;
static struct ev_timer watcher_timer;
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop) {
printf("create loop failed\r\n");
return NULL;
}
ev_io_init (&watcher_b, watcher_b_cb, Bloop_ctrl->ba.s, EV_READ);
ev_timer_init(&watcher_timer, watcher_timer_cb, 5, 1);
ev_io_start (loop, &watcher_b);
ev_timer_start (loop, &watcher_timer);
return loop;
}
void *B_thread(void *arg)
{
Bloop_ctrl_t Bloop_ctrl;
if (B_nanomsg_init(&Bloop_ctrl) < 0) {
printf("nanomsg init failed\r\n");
return ;
}
struct ev_loop* Bloop = B_loop_init(&Bloop_ctrl);
if (NULL == Bloop) {
printf("Bloop init failed\r\n");
return ;
}
ev_set_userdata(Bloop, &Bloop_ctrl);
ev_run (Bloop, 0);
return ;
}
/*****************************************主线程A相关**********************************************/
static void watcher_ab_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
void *user_data = ev_userdata(loop);
Aloop_ctrl_t *Aloop_ctrl = (Aloop_ctrl_t *)user_data;
uint8_t *dat = NULL;
uint32_t bytes = nn_recv(Aloop_ctrl->ab.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0) {
return;
}
//转发到C
printf("A:%s (B->A)\r\n", (char *)dat);
nn_send(Aloop_ctrl->ac.n, &dat, NN_MSG, NN_DONTWAIT);
}
static void watcher_ac_cb (struct ev_loop *loop ,struct ev_io *w, int revents)
{
void *user_data = ev_userdata(loop);
Aloop_ctrl_t *Aloop_ctrl = (Aloop_ctrl_t *)user_data;
uint8_t *dat = NULL;
uint32_t bytes = nn_recv(Aloop_ctrl->ac.n, &dat, NN_MSG, NN_DONTWAIT);
if (bytes <= 0) {
return;
}
//转发到B
printf("A:%s (C->A)\r\n", (char *)dat);
nn_send(Aloop_ctrl->ab.n, &dat, NN_MSG, NN_DONTWAIT);
}
/*主事件nanomsg初始化*/
int A_nanomsg_init(Aloop_ctrl_t *Aloop_ctrl)
{
//ab通信的nanomsg初始化
Aloop_ctrl->ab.n = nn_socket(AF_SP, NN_PAIR);
if (Aloop_ctrl->ab.n < 0) {
return -1;
}
if (nn_bind(Aloop_ctrl->ab.n, "inproc://b2a_loop") < 0) {
return -1;
}
//获取此端口的接收数据fd描述符
size_t size = sizeof(size_t);
if (nn_getsockopt(Aloop_ctrl->ab.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&Aloop_ctrl->ab.s, &size) < 0) {
return -1;
}
//ac通信的nanomsg初始化
Aloop_ctrl->ac.n = nn_socket(AF_SP, NN_PAIR);
if (Aloop_ctrl->ac.n < 0) {
return -1;
}
if (nn_bind(Aloop_ctrl->ac.n, "inproc://c2a_loop") < 0) {
return -1;
}
//获取此端口的接收数据fd描述符
if (nn_getsockopt(Aloop_ctrl->ac.n, NN_SOL_SOCKET, NN_RCVFD, (char *)&Aloop_ctrl->ac.s, &size) < 0) {
return -1;
}
return 0;
}
/*主事件循环初始化*/
struct ev_loop* A_loop_init(Aloop_ctrl_t *Aloop_ctrl)
{
static struct ev_io watcher_ab, watcher_ac;
struct ev_loop *loop = ev_loop_new(EVBACKEND_EPOLL);
if (NULL == loop) {
printf("create loop failed\r\n");
return NULL;
}
//传参
ev_set_userdata(loop, Aloop_ctrl);
//初始化
ev_io_init (&watcher_ab, watcher_ab_cb, Aloop_ctrl->ab.s, EV_READ);
ev_io_init (&watcher_ac, watcher_ac_cb, Aloop_ctrl->ac.s, EV_READ);
ev_io_start (loop, &watcher_ab);
ev_io_start (loop, &watcher_ac);
return loop;
}
/**************************************************************************************************/
int main()
{
pthread_t pb,pc;
Aloop_ctrl_t Aloop_ctrl;
if (A_nanomsg_init(&Aloop_ctrl) < 0) {
printf("nanomsg init failed\r\n");
return -1;
}
struct ev_loop* Aloop = A_loop_init(&Aloop_ctrl);
if (NULL == Aloop) {
printf("Aloop init failed\r\n");
return -1;
}
//创建线程B
if (0 != pthread_create(&pb, NULL, B_thread, NULL)) {
printf("create pthread B failed\r\n");
return -1;
}
//创建线程C
if (0 != pthread_create(&pc, NULL, C_thread, NULL)) {
printf("create pthread C failed\r\n");
return -1;
}
//运行
ev_run(Aloop, 0);
return 0;
}
//编译
gcc -o ev_nanomsg ev_nanomsg.c -lev -lnanomsg -lpthread
//运行结果
A:Please turn on LED[1] (B->A)
C:Please turn on LED[1] (A->C)
A:OK (C->A)
B:OK (A->B)