基于libqb的IPC通讯
1.libqb的基本说明:
libqb库主要目的是提供高性能C/S可重用的特性,它提供了高性能日志记录、跟踪、ipc通讯和poll等。
libqb库注重api的实现,高度调整最大的客户机/服务器应用程序的性能。
2.libqb源码下载:
git clone git://github.com/ClusterLabs/libqb.git
3.在linux环境下的编译:
libqb的实现考虑到了跨平台的使用,所以开发基于glib,Makefile也是使用了automake及libtool等自动生成Makefile。
1)环境配置:
安装autoconf:
yum install autoconf
安装automake:
yum install automake
安装libtool:
yum install libtool
2)生成Makefile
执行Makefile生成脚本:
./autogen.sh && ./configure
即生成编译Makefile
3)编译安装:
make && make install
编译生成动态库libqb.so,并将相关头文件安装在/usr/include目录下
4.使用libqb编写进程通讯server端:
1)包含libqb相关头文件:
#include <signal.h> #include <qb/qbdefs.h> #include <qb/qbutil.h> #include <qb/qblog.h> #include <qb/qbloop.h> #include <qb/qbipcs.h> #include "os_base.h"
2) 先定义好需要使用的消息结构:
struct srv_req { struct qb_ipc_request_header hdr; char message[256]; };
3) 设置IPC通讯类型,注册server端事件处理函数:
enum qb_ipc_type ipc_type = QB_IPC_NATIVE; struct qb_ipcs_service_handlers sh = { .connection_accept = connection_accept_fn, .connection_created = connection_created_fn, .msg_process = msg_process_fn, .connection_destroyed = connection_destroyed_fn, .connection_closed = connection_closed_fn, }; struct qb_ipcs_poll_handlers ph = { .job_add = my_job_add, .dispatch_add = srv_dispatch_add, .dispatch_mod = srv_dispatch_mod, .dispatch_del = srv_dispatch_del, };
server跑起来后,接收到client发送过来的数据都会触发qb_ipcs_service_handlers结构中的
.msg_proscess回调函数,例如上面注册好的函数:
void msg_process_fn(qb_ipcs_connection_t * c, void *data, size_t size) { struct srv_req *req_pt; hdr = (struct qb_ipc_request_header *)data; if (hdr->id == (QB_IPC_MSG_USER_START + 1))
return 0; req_pt = (struct srv_req *)data; printf( "msg received (id:%d, size:%d, data:%s)", req_pt->hdr.id, req_pt->hdr.size, req_pt->message); }
在 msg_process_fn回调函数中,可以进行client发过来的消息处理。
4)使用注册好的handle创建IPC server,并运行,此处以"testserver"命名server:
static qb_loop_t *bms_loop; static qb_ipcs_service_t *s1; s1 = qb_ipcs_create("testserver", 0, ipc_type, &sh); if (s1 == 0) { qb_perror(LOG_ERR, "qb_ipcs_create"); exit(1); } /* This forces the clients to use a minimum buffer size */ qb_ipcs_enforce_buffer_size(s1, ONE_MEG); bms_loop = qb_loop_create(); qb_ipcs_poll_handlers_set(s1, &ph); rc = qb_ipcs_run(s1); if (rc != 0) { errno = -rc; qb_perror(LOG_ERR, "qb_ipcs_run"); exit(1); } qb_loop_run(bms_loop);
5.有了IPC server端,client端只需要连接上命名好的serve,即可开始通讯收发消息:
首先定义一个connect变量:qb_ipcc_connection_t *conn;
然后定义自己的消息结构体:
struct srv_req { struct qb_ipc_request_header hdr; char message[256]; }; struct srv_res { struct qb_ipc_response_header hdr; char message[256]; };
connect server成功后,即可send 数据给server(testserver)端:
conn = qb_ipcc_connect("testserver", 0); if (conn == NULL) { perror("qb_ipcc_connect"); exit(1); }
例如,可以调用send api:qb_ipcc_send发送数据,并处理接收返回数据:
struct srv_req req; struct srv_res res; char *newline; int32_t rc; int32_t send_ten_events; while (1) { printf("SEND (q or Q to quit) : "); if (fgets(req.message, 256, stdin) == NULL) continue; newline = strrchr(req.message, '\n'); if (newline) { *newline = '\0'; } if (strcasecmp(req.message, "q") == 0) { break; }
else { req.hdr.id = QB_IPC_MSG_USER_START + 3; req.hdr.size = sizeof(struct my_req); rc = qb_ipcc_send(conn, &req, req.hdr.size); if (rc < 0) { perror("qb_ipcc_send"); exit(0); }
} }
client send结束后,释放qb_ipcc_connection_t:
qb_ipcc_disconnect(conn);