在开始使用以前,咱们须要先搞清楚libevent编译生成的各个动态库的做用。
在下载libevent源码包进行编译之后,当前目录生成.libs目录,该目录下是全部的目标文件,这里咱们只说明个动态库so文件的做用,经过makefile咱们能够知道各个动态库包含内容:缓存
动态库名称 | 做用 |
---|---|
libevent_core.so | 这个库包含了全部核心的事件和缓存功能 |
libevent_extra.so | 这个库包含外围的dns、rpc、http等协议使用 |
libevent.so | 这个库包含了libevent_core和libevent_extra的内容 |
libevent_openssl.so | 须要进行加密通讯时能够使用这个 |
libevent_pthreads.so | 看名字就知道若是要用多线程的方式使用libevent,就须要用到这个库 |
下面使用libevent实现了一个很简单的服务端和客户端程序。多线程
//server-event.cpp #include <string.h> #include <errno.h> #include <stdio.h> #include <signal.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <event2/bufferevent.h> #include <event2/buffer.h> #include <event2/listener.h> #include <event2/util.h> #include <event2/event.h> static const int PORT = 9995; static char g_szWriteMsg[256] = {0}; static char g_szReadMsg[256] = {0}; static int g_iCnt = 0; static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); static void conn_writecb(struct bufferevent *, void *); static void conn_readcb(struct bufferevent *, void *); static void conn_eventcb(struct bufferevent *, short, void *); int main(int argc, char **argv) { struct event_base *base; struct evconnlistener *listener; struct event *signal_event; struct sockaddr_in sin; base = event_base_new(); if (!base) { fprintf(stderr, "Could not initialize libevent!\n"); return 1; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(PORT);//固定一个端口号 //建立、绑定、监听socket listener = evconnlistener_new_bind(base, listener_cb, (void *)base, LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1, (struct sockaddr*)&sin, sizeof(sin)); if (!listener) { fprintf(stderr, "Could not create a listener!\n"); return 1; } event_base_dispatch(base); evconnlistener_free(listener); //event_free(signal_event); event_base_free(base); printf("done\n"); return 0; } //有链接来时调用 static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) { struct event_base *base = (struct event_base*)user_data; struct bufferevent *bev; //构造一个bufferevent bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); if (!bev) { fprintf(stderr, "Error constructing bufferevent!"); event_base_loopbreak(base); return; } //绑定读事件回调函数、写事件回调函数、错误事件回调函数 bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL); bufferevent_enable(bev, EV_WRITE); bufferevent_enable(bev, EV_READ); const char *szMsg = "hi client!"; bufferevent_write(bev, szMsg, strlen(szMsg)); } static void conn_writecb(struct bufferevent *bev, void *user_data) { //printf("touch conn_writecb\n"); // if ( strlen(g_szWriteMsg) > 0 ) // { // bufferevent_write(bev, g_szWriteMsg, strlen(g_szWriteMsg)); // memset(g_szWriteMsg, 0x00, sizeof(g_szWriteMsg)); // } } static void conn_readcb(struct bufferevent *bev, void *user_data) { //printf("touch conn_readcb\n"); memset(g_szReadMsg, 0x00, sizeof(g_szReadMsg)); struct evbuffer *input = bufferevent_get_input(bev); size_t sz = evbuffer_get_length(input); if (sz > 0) { bufferevent_read(bev, g_szReadMsg, sz); printf("cli:>>%s\n", g_szReadMsg); memset(g_szWriteMsg, 0x00, sizeof(g_szWriteMsg)); snprintf(g_szWriteMsg, sizeof(g_szWriteMsg)-1, "hi client, this count is %d", g_iCnt); g_iCnt++; //printf("ser:>>"); //gets(g_szWriteMsg); //scanf("%s", g_szWriteMsg); bufferevent_write(bev, g_szWriteMsg, strlen(g_szWriteMsg)); } } static void conn_eventcb(struct bufferevent *bev, short events, void *user_data) { if (events & BEV_EVENT_EOF) { printf("Connection closed.\n"); } else if (events & BEV_EVENT_ERROR) { printf("Got an error on the connection: %s\n", strerror(errno));/*XXX win32*/ } /* None of the other events can happen here, since we haven't enabled * timeouts */ bufferevent_free(bev); }
//client-event.cpp #include <string.h> #include <errno.h> #include <stdio.h> #include <signal.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <event2/bufferevent.h> #include <event2/buffer.h> #include <event2/listener.h> #include <event2/util.h> #include <event2/event.h> static const int PORT = 9995; static char g_szWriteMsg[256] = {0}; static char g_szReadMsg[256] = {0}; static int g_iCnt = 0; static void conn_writecb(struct bufferevent *, void *); static void conn_readcb(struct bufferevent *, void *); static void conn_eventcb(struct bufferevent *, short, void *); int main(int argc, char **argv) { struct event_base *base; struct sockaddr_in sin; base = event_base_new(); if (!base) { fprintf(stderr, "Could not initialize libevent!\n"); return 1; } memset(&sin, 0, sizeof(sin)); sin.sin_addr.s_addr = inet_addr("192.168.233.250"); sin.sin_family = AF_INET; sin.sin_port = htons(PORT); struct bufferevent* bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); if (bev == NULL ) { fprintf(stderr, "socket init failed\n"); return 1; } bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL); //链接服务端 int flag = bufferevent_socket_connect(bev, (struct sockaddr*)&sin, sizeof(sin)); if (-1 == flag ) { fprintf(stderr, "connect failed\n"); return 1; } bufferevent_enable(bev, EV_READ | EV_WRITE); event_base_dispatch(base); event_base_free(base); printf("done\n"); return 0; } static void conn_writecb(struct bufferevent *bev, void *user_data) { //printf("touch conn_writecb\n"); // if ( strlen(g_szWriteMsg) > 0 ) // { // bufferevent_write(bev, g_szWriteMsg, strlen(g_szWriteMsg)); // memset(g_szWriteMsg, 0x00, sizeof(g_szWriteMsg)); // } } static void conn_readcb(struct bufferevent *bev, void *user_data) { //printf("touch conn_readcb\n"); memset(g_szReadMsg, 0x00, sizeof(g_szReadMsg)); struct evbuffer *input = bufferevent_get_input(bev); size_t sz = evbuffer_get_length(input); if (sz > 0) { bufferevent_read(bev, g_szReadMsg, sz); printf("ser:>>%s\n", g_szReadMsg); memset(g_szWriteMsg, 0, sizeof(g_szWriteMsg)); snprintf(g_szWriteMsg, sizeof(g_szWriteMsg)-1, "hi server,this count is %d", g_iCnt); g_iCnt++; //printf("cli:>>"); //gets(g_szWriteMsg); //scanf("%s", g_szWriteMsg); bufferevent_write(bev, g_szWriteMsg, strlen(g_szWriteMsg)); } } static void conn_eventcb(struct bufferevent *bev, short events, void *user_data) { if (events & BEV_EVENT_EOF) { printf("Connection closed.\n"); } else if (events & BEV_EVENT_ERROR) { printf("Got an error on the connection: %s\n", strerror(errno));/*XXX win32*/ } else if(events & BEV_EVENT_CONNECTED) { //链接成功时走这里,而且要客户端第一次触发读事件后链接才真正创建起来 printf("connect success\n"); const char* msg = "hi server,hao are you"; bufferevent_write(bev, msg, strlen(msg)); return; } bufferevent_free(bev); }
上面服务端和客户端代码使用libevent创建了一个简单的聊天应用,编译时需连接-levent_core。app
文章同步发表在cpp加油站(ID:xy13640954449), 欢迎关注!