在開始使用以前,咱們須要先搞清楚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), 歡迎關注!