1. Libevent介紹
Libevent 是一個(gè)用C語言編寫的、輕量級(jí)的開源高性能事件通知庫,主要有以下幾個(gè)亮點(diǎn):
- 事件驅(qū)動(dòng)( event-driven),高性能;
- 輕量級(jí),專注于網(wǎng)絡(luò);
- 源代碼相當(dāng)精煉、易讀;
- 支持多種 I/O 多路復(fù)用技術(shù), epoll、 poll、 select 和 kqueue 等;
- 支持注冊(cè)事件優(yōu)先級(jí)。
1.1 安裝Libevent
下載地址: http://http://libevent.org/
安裝步驟 -> 源碼安裝的方式(終端打開下載目錄)
1. 可執(zhí)行程序: configure
./configure // 檢測安裝環(huán)境, 并且生成一個(gè)makefile文件
2. 根據(jù)makefile中的構(gòu)建規(guī)則編譯源代碼
make
3. 安裝
sudo make install //將得到可執(zhí)行程序/動(dòng)態(tài)庫/靜態(tài)庫/頭文件拷貝到系統(tǒng)目錄
動(dòng)態(tài)庫找不到問題解決:
- 通過find命令查找對(duì)應(yīng)的庫的位置
find 搜索目錄 -name "http://libevent.so"
得到結(jié)果: /usr/local/lib/libevent.so
- 通過vi 打開/etc/ld.so.conf文件
sudo /etc/ld.so.conf
將/usr/local/lib/放到文件的最后一行, 保存
- 執(zhí)行命令: sudo ldconfig
編譯要加上動(dòng)態(tài)庫event hello.c
gcc hello.c -o hello -levent
2. 事件處理框架 - event_base
使用 libevent函數(shù)之前需要分配一個(gè)或者多個(gè) event_base 結(jié)構(gòu)體。每個(gè)event_base 結(jié)構(gòu)體持有一個(gè)事件集合,可以檢測以確定哪個(gè)事件是激活的。每個(gè) event_base 都有一種用于檢測哪種事件已經(jīng)就緒的 “方法”。
2.1 event_base API函數(shù)
// 頭文件
#include < event2/event.h >
// 操作函數(shù)
struct event_base * event_base_new(void); //創(chuàng)建事件處理框架
void event_base_free(struct event_base * base); //釋放事件處理框架
// 檢查event_base的后端方法
const char** event_get_supported_methods(void);
const char *event_base_get_method(const struct event_base *base);
event_base和fork(進(jìn)程)關(guān)系:
- 子進(jìn)程創(chuàng)建成功之后, 父進(jìn)程可以繼續(xù)使用event_base
- 子進(jìn)程中需要繼續(xù)使用event_base需要用下面函數(shù),重新初始化
int event_reinit(struct event_base* base);
例子:
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < event2/event.h >
int main()
{
// 1. 創(chuàng)建事件處理框架
struct event_base* base = event_base_new();
// 打印支持的IO轉(zhuǎn)接函數(shù)
const char** method = event_get_supported_methods();
for(int i=0; method[i] != NULL; ++i)
{
printf("%sn", method[i]);
}
printf("current method: %sn", event_base_get_method(base));
// 創(chuàng)建子進(jìn)程
pid_t pid = fork();
if(pid == 0)
{
// 子進(jìn)程中event_base也會(huì)被復(fù)制,在使用這個(gè)base時(shí)候要重新初始化
event_reinit(base);
}
// 2. 釋放資源
event_base_free(base);
return 0;
}
3. 事件循環(huán)
event_base不停的檢測委托的檢測是實(shí)際是不是發(fā)生了, 如果發(fā)生了, event_base會(huì)調(diào)用對(duì)應(yīng)的回調(diào)函數(shù), 這個(gè)回調(diào)函數(shù)的用戶委托檢測事件的時(shí)候給的.
3.1 設(shè)置事件循環(huán)
如果委托了event_base檢測某些事件, 不停的進(jìn)行循環(huán)檢測
結(jié)束檢測時(shí)間: 所有要檢測的事件都被觸發(fā), 并且處理完畢。
// 頭文件
#include < event2/event.h >
// 操作函數(shù)
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
int event_base_loop(struct event_base *base, int flags);
參數(shù):
- base: 通過 event_base_new(void)得到的
- flags:
- EVLOOP_ONCE: 一直檢測某個(gè)事件, 當(dāng)事件被觸發(fā)了, 停止事件循環(huán)
- EVLOOP_NONBLOCK: 非阻塞的方式檢測, 當(dāng)事件被觸發(fā)了, 停止事件循環(huán)
- EVLOOP_NO_EXIT_ON_EMPTY: 一直進(jìn)行事件檢測, 如果沒有要檢測的事件, 不退出
int event_base_dispatch(struct event_base* base); // 一般使用這個(gè)函數(shù)
參數(shù):
- base: 通過 event_base_new(void)得到的
3.2 終止事件循環(huán)
// 頭文件
#include < event2/event.h >
struct timeval {
long tv_sec;
long tv_usec; // 微秒
};
// 在 tv 時(shí)長之后退出循環(huán), 如果這個(gè)參數(shù)為空NULL, 直接退出事件循環(huán)
// 事件循環(huán): 檢測對(duì)應(yīng)的事件是否被觸發(fā)了
// 如果事件處理函數(shù)正在被執(zhí)行, 執(zhí)行完畢之后才終止
int event_base_loopexit(struct event_base * base, const struct timeval * tv);
// 馬上終止
int event_base_loopbreak(struct event_base * base);
4. 事件
4.1 事件基本操作
- 事件的創(chuàng)建 event_new
#include < event2/event.h >
//要檢測事件 what:
#define EV_TIMEOUT 0x01
#define EV_READ 0x02
#define EV_WRITE 0x04
#define EV_SIGNAL 0x08
#define EV_PERSIST 0x10 // 修飾某個(gè)事件是持續(xù)觸發(fā)的
#define EV_ET 0x20 // 邊沿模式
//回調(diào)函數(shù)格式:
typedef void (*event_callback_fn)(evutil_socket_t,short,void *);
參數(shù):
- 第一個(gè)參數(shù): event_new的第二個(gè)參數(shù)
- 第二個(gè)參數(shù): 實(shí)際觸發(fā)的事件
- 第三個(gè)參數(shù): event_new的最后一個(gè)參數(shù)
// 創(chuàng)建事件
struct event* event_new(struct event_base * base,evutil_socket_t fd,
short what,event_callback_fn cb,void * arg);
參數(shù):
- base: event_base_new得到的
- fd: 文件描述符, 檢測這個(gè)fd對(duì)應(yīng)的事件
- what: 監(jiān)測fd的什么事件
- cb: 回調(diào)函數(shù), 當(dāng)前檢測的事件被觸發(fā), 這個(gè)函數(shù)被調(diào)用
- arg: 給回調(diào)函數(shù)傳參
- 事件的釋放
#include < event2/event.h >
// 釋放事件資源
void event_free(struct event * event);
- 事件的添加、刪除
事件被new出之后, 不能直接被event_base進(jìn)行檢測event_add之后event_base就可以對(duì)事件進(jìn)行檢測
#include < event2/event.h >
int event_add(struct event * ev,const struct timeval * tv);
參數(shù): tv- > 超時(shí)時(shí)間,
如果這個(gè)值 > 0, 比如 == 3
檢測fd的讀事件, 在三秒之內(nèi)沒有觸發(fā)該事件 - > 超時(shí)- > 超時(shí)之后, 事件對(duì)應(yīng)的回調(diào)函數(shù)會(huì)被強(qiáng)制調(diào)用
如果該參數(shù)為NULL, 不會(huì)做超時(shí)檢測
// 刪除要檢測的事件
int event_del(struct event * ev);
4.2 事件的優(yōu)先級(jí)設(shè)置
// 頭文件
#include < event2/event.h >
// EVENT_MAX_PRIORITIES == 256 最大的初始化事件優(yōu)先級(jí)
int event_base_priority_init(struct event_base * base,int n_priorities);
參數(shù):
- n_priorities: 等級(jí)的個(gè)數(shù), 假設(shè) == 6
也就是說有6個(gè)等級(jí): 0,1,2,3,4,5, 0優(yōu)先級(jí)最高
// 獲取當(dāng)前可用的等的個(gè)數(shù)
int event_base_get_npriorities(struct event_base * base);
// 給事件設(shè)置等級(jí)
int event_priority_set(struct event *event, int priority);
參數(shù):
- event: 創(chuàng)建的事件
- priority: 要設(shè)置的等級(jí)
例子:使用event實(shí)現(xiàn)有名管道的進(jìn)程間通信myfifo
myfifo管道文件要提前創(chuàng)造好
讀端:
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < event2/event.h >
#include < fcntl.h >
//讀的回調(diào)函數(shù)
void read_cb(evutil_socket_t fd, short what, void* arg)
{
char buf[128];
int count = read(fd, buf, sizeof(buf)+1);
printf("read data: %s, %dn", buf, count);
printf("read event: %sn", what & EV_READ ? "yes" : "no");
printf("what: %dnn", what);
}
int main()
{
int fd = open("myfifo", O_RDONLY);
if (fd == -1)
{
perror("open");
exit(0);
}
struct event_base* base = event_base_new();
//創(chuàng)建事件
struct event* ev = event_new(base, fd, EV_READ|EV_PERSIST, read_cb, NULL);
//添加事件
event_add(ev, NULL);
//事件循環(huán)檢測
event_base_dispatch(base);
//釋放資源
event_free(ev);
event_base_free(base);
return 0;
}
寫端:
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < event2/event.h >
#include < fcntl.h >
//讀的回調(diào)函數(shù)
void write_cb(evutil_socket_t fd, short what, void* arg)
{
char buf[128];
static int num = 0;
sprintf(buf, "hello, %dn", num++);
int count = write(fd, buf, sizeof(buf)+1);
printf("wirte data: %s, %dn", buf, count);
printf("wirte event: %sn", what & EV_WRITE ? "yes" : "no");
printf("what: %dnn", what);
sleep(3);
}
int main()
{
int fd = open("myfifo", O_WRONLY);
if (fd == -1)
{
perror("open");
exit(0);
}
struct event_base* base = event_base_new();
//創(chuàng)建事件
struct event* ev = event_new(base, fd, EV_WRITE|EV_PERSIST, write_cb, NULL);
//添加事件
event_add(ev, NULL);
//事件循環(huán)檢測
event_base_dispatch(base);
//釋放資源
event_free(ev);
event_base_free(base);
return 0;
}
5. 帶緩沖區(qū)的事件
概念理解:
- bufferevent 理解:
- 是libevent為IO緩沖區(qū)操作提供的一種通用機(jī)制
- bufferevent 由一個(gè)底層的傳輸端口(如套接字 ), 一個(gè)讀取緩沖區(qū)和一個(gè)寫入緩沖區(qū)組成。
- 與通常的事件在底層傳輸端口已經(jīng)就緒, 可以讀取或者寫入的時(shí)候執(zhí)行回調(diào)不同的是, bufferevent在讀取或者寫入了足夠量的數(shù)據(jù)之后調(diào)用用戶提供的回調(diào)。
- 每個(gè) bufferevent 有兩個(gè)數(shù)據(jù)相關(guān)的回調(diào)
- 讀取回調(diào): 從底層傳輸端口讀取了任意量的數(shù)據(jù)之后會(huì)調(diào)用讀取回調(diào)(默認(rèn))
- 寫入回調(diào): 輸出緩沖區(qū)中足夠量的數(shù)據(jù)被清空到底層傳輸端口后寫入回調(diào)會(huì)被調(diào)用(默認(rèn))
創(chuàng)建/釋放基于套接字的bufferevent bufferevent_socket_new
主要應(yīng)用于網(wǎng)絡(luò)套接字通信 -> socket()
struct bufferevent *bufferevent_socket_new(
struct event_base *base,
evutil_socket_t fd,
enum bufferevent_options options
);
參數(shù):
- base: 處理事件的
- fd: 通信的文件描述符
- options: BEV_OPT_CLOSE_ON_FREE - > 自動(dòng)釋放底層資源
返回值: 得到帶緩沖區(qū)的事件變量
// 釋放資源
void bufferevent_free(struct bufferevent *bev);
在bufferevent上啟動(dòng)連接服務(wù)器函數(shù) bufferevent_socket_connect
- 如果還沒有為bufferevent 設(shè)置套接字,調(diào)用函數(shù)將為其分配一個(gè)新的流套接字,并且設(shè)置為非阻塞的
例子:bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
- 如果已經(jīng)為 bufferevent 設(shè)置套接字,調(diào)用bufferevent_socket_connect() 將告知 libevent 套接字還未連接,直到連接成功之前不應(yīng)該對(duì)其進(jìn)行讀取或者寫入操作。
- 連接完成之前可以向輸出緩沖區(qū)添加數(shù)據(jù)。
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
參數(shù):
- bev: 帶緩沖區(qū)的事件, 里邊封裝 fd
- address: 要連接的服務(wù)器的IP和端口
- addrlen: address結(jié)構(gòu)體的內(nèi)存大小
bufferevent讀寫緩沖區(qū)回調(diào)操作 bufferevent_setcb
//讀、寫事件觸發(fā)之后的回調(diào)函數(shù)格式
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void *ctx);
參數(shù):
- bev: 從bufferevent_setcb函數(shù)中的第一個(gè)參數(shù)傳入的
- ctx: 從bufferevent_setcb函數(shù)中的最后第一個(gè)參數(shù)傳入的
//特殊事件的回調(diào)函數(shù)格式
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);
參數(shù):
- bev: 從bufferevent_setcb函數(shù)中的第一個(gè)參數(shù)傳入的
- events: 可以檢測到的事件
EV_EVENT_READING:讀取操作時(shí)發(fā)生某事件,具體是哪種事件請(qǐng)看其他標(biāo)志。
BEV_EVENT_WRITING:寫入操作時(shí)發(fā)生某事件,具體是哪種事件請(qǐng)看其他標(biāo)志。
BEV_EVENT_ERROR:操作時(shí)發(fā)生錯(cuò)誤。關(guān)于錯(cuò)誤的更多信息,請(qǐng)調(diào)用 EVUTIL_SOCKET_ERROR()。
BEV_EVENT_TIMEOUT:發(fā)生超時(shí)。
BEV_EVENT_EOF:遇到文件結(jié)束指示。
BEV_EVENT_CONNECTED:請(qǐng)求的連接過程已經(jīng)完成
void bufferevent_setcb(struct bufferevent *bufev,
bufferevent_data_cb readcb,
bufferevent_data_cb writecb,
bufferevent_event_cb eventcb, void *cbarg
);
參數(shù):
- bufev: 帶緩沖區(qū)的事件
- readcb: 讀事件觸發(fā)之后的回調(diào)函數(shù)
- writecb: 寫事件觸發(fā)之后的回調(diào)函數(shù)
- eventcb: 特殊事件的回調(diào)函數(shù)
- cbarg: 給回調(diào)函數(shù)傳參
禁用、啟用緩沖區(qū)
可以啟用或者禁用 bufferevent 上的 EV_READ、EV_WRITE 或者 EV_READ | EV_WRITE 事件。
沒有啟用讀取或者寫入事件時(shí), bufferevent 將不會(huì)試圖進(jìn)行數(shù)據(jù)讀取或者寫入。
寫緩沖區(qū)默認(rèn)是有效的,讀緩沖區(qū)默認(rèn)無效
// 設(shè)置某個(gè)事件有效
void bufferevent_enable(struct bufferevent *bufev, short events);
// 設(shè)置某個(gè)事件無效
void bufferevent_disable(struct bufferevent *bufev, short events);
// 獲取緩沖區(qū)對(duì)應(yīng)的有效事件
short bufferevent_get_enabled(struct bufferevent *bufev);
操作bufferevent中的數(shù)據(jù) bufferevent_write bufferevent_read
// 向bufferevent的輸出緩沖區(qū)添加數(shù)據(jù)
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
// 從bufferevent的輸入緩沖區(qū)移除數(shù)據(jù)
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
6. 鏈接監(jiān)聽器
- 創(chuàng)建和釋放evconnlistener
#include < event2/listener.h >
//回調(diào)函數(shù)格式
typedef void (*evconnlistener_cb)(
struct evconnlistener *listener,
evutil_socket_t sock,
struct sockaddr *addr,
int len,
void *ptr
);
參數(shù):
- listener: evconnlistener_new_bind 返回的地址
- sock: 用于通信的fd
- addr: 客戶端的地址信息
- ptr: 外部傳進(jìn)來的參數(shù), evconnlistener_new_bind的第三個(gè)參數(shù)
// 創(chuàng)建監(jiān)聽的套接字, 綁定, 設(shè)置監(jiān)聽, 等待并接受連接請(qǐng)求
struct evconnlistener *evconnlistener_new_bind(
struct event_base *base,
evconnlistener_cb cb, // 接受新連接之后的回調(diào)函數(shù)
void *ptr, // 回調(diào)函數(shù)參數(shù)
unsigned flags,
int backlog, // listen()中的第二參數(shù),最多的監(jiān)聽數(shù)量,小于128的整數(shù)
const struct sockaddr *sa, // 本地的IP和端口
int socklen // struct sockaddr結(jié)構(gòu)體大小
);
參數(shù):
- flags:
LEV_OPT_CLOSE_ON_FREE: 自動(dòng)關(guān)閉底層套接字
LEV_OPT_REUSEABLE: 設(shè)置端口復(fù)用
// 釋放
void evconnlistener_free(struct evconnlistener *lev);
- 啟用和禁用 evconnlistener
設(shè)置無效之后, 就不監(jiān)聽連接請(qǐng)求了
#include < event2/listener.h >
int evconnlistener_disable(struct evconnlistener *lev);
int evconnlistener_enable(struct evconnlistener *lev);
- 調(diào)整 evconnlistener 的回調(diào)函數(shù)
#include < event2/listener.h >
void evconnlistener_set_cb(struct evconnlistener *lev, evconnlistener_cb cb, void *arg);
7. 例子:用event實(shí)現(xiàn)服務(wù)器和客戶端tcp通信
服務(wù)器使用鏈接監(jiān)聽器、帶緩沖區(qū)的事件
客戶端使用帶緩沖區(qū)的事件
服務(wù)器server代碼:
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < arpa/inet.h >
#include < event2/event.h >
#include < event2/bufferevent.h >
#include < event2/listener.h >
// read緩沖區(qū)的回調(diào)
void read_cb(struct bufferevent* bev, void* arg)
{
// 讀緩沖區(qū)的數(shù)據(jù)
char buf[128];
int len = bufferevent_read(bev, buf, sizeof(buf));
printf("read data: len = %d, str = %sn", len, buf);
// 回復(fù)數(shù)據(jù)
bufferevent_write(bev, buf, len);
printf("數(shù)據(jù)發(fā)送完畢...n");
}
// 寫緩沖區(qū)的回調(diào)
// 調(diào)用的時(shí)機(jī): 寫緩沖區(qū)中的數(shù)據(jù)被發(fā)送出去之后, 該函數(shù)被調(diào)用
void write_cb(struct bufferevent* bev, void* arg)
{
printf("arg value: %sn", (char*)arg);
printf("數(shù)據(jù)已經(jīng)發(fā)送完畢...xxxxxxxxxxxxn");
}
// 事件回調(diào)
void events_cb(struct bufferevent* bev, short event, void* arg)
{
if(event & BEV_EVENT_ERROR)
{
printf("some error happened ...n");
}
else if(event & BEV_EVENT_EOF)
{
printf("server disconnect ...n");
}
// 終止連接
bufferevent_free(bev);
}
// 接收連接請(qǐng)求之后的回調(diào)
void listener_cb(struct evconnlistener *listener,
evutil_socket_t sock,
struct sockaddr *addr,
int len,
void *ptr)
{
// 通信
// 使用帶緩沖區(qū)的事件對(duì)sock進(jìn)行包裝
struct event_base* base = (struct event_base*)ptr;
struct bufferevent* bev = bufferevent_socket_new(base, sock, BEV_OPT_CLOSE_ON_FREE);
// 設(shè)置回調(diào)
bufferevent_setcb(bev, read_cb, write_cb, events_cb, NULL);
bufferevent_enable(bev, EV_READ);
}
int main()
{
struct event_base * base = event_base_new();
// 1. 創(chuàng)建監(jiān)聽的套接字, 綁定, 設(shè)置監(jiān)聽, 等待并接受連接請(qǐng)求
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9898); // 服務(wù)器監(jiān)聽的端口
addr.sin_addr.s_addr = INADDR_ANY;
struct evconnlistener* listener = evconnlistener_new_bind(base, listener_cb, base,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
100, (struct sockaddr*)&addr, sizeof(addr));
event_base_dispatch(base);
evconnlistener_free(listener);
event_base_free(base);
return 0;
}
客戶端client代碼:
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < arpa/inet.h >
#include < event2/event.h >
#include < event2/bufferevent.h >
// read緩沖區(qū)的回調(diào)
void read_cb(struct bufferevent* bev, void* arg)
{
printf("arg value: %sn", (char*)arg);
// 讀緩沖區(qū)的數(shù)據(jù)
char buf[128];
int len = bufferevent_read(bev, buf, sizeof(buf));
printf("read data: len = %d, str = %sn", len, buf);
// 回復(fù)數(shù)據(jù)
bufferevent_write(bev, buf, len);
printf("數(shù)據(jù)發(fā)送完畢...n");
}
// 寫緩沖區(qū)的回調(diào)
// 調(diào)用的時(shí)機(jī): 寫緩沖區(qū)中的數(shù)據(jù)被發(fā)送出去之后, 該函數(shù)被調(diào)用
void write_cb(struct bufferevent* bev, void* arg)
{
printf("arg value: %sn", (char*)arg);
printf("數(shù)據(jù)已經(jīng)發(fā)送完畢...xxxxxxxxxxxxn");
}
// 事件回調(diào)
void events_cb(struct bufferevent* bev, short event, void* arg)
{
if(event & BEV_EVENT_ERROR)
{
printf("some error happened ...n");
}
else if(event & BEV_EVENT_EOF)
{
printf("server disconnect ...n");
}
// 終止連接
bufferevent_free(bev);
}
void send_msg(evutil_socket_t fd, short ev, void * arg)
{
// 將寫入到終端的數(shù)據(jù)讀出
char buf[128];
int len = read(fd, buf, sizeof(buf));
// 發(fā)送給服務(wù)器
struct bufferevent* bev = (struct bufferevent*)arg;
bufferevent_write(bev, buf, len);
}
int main()
{
struct event_base * base = event_base_new();
// 1. 創(chuàng)建通信的套接字
struct bufferevent* bufev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
// 2. 連接服務(wù)器
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9898); // 服務(wù)器監(jiān)聽的端口
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
// 這個(gè)函數(shù)調(diào)用成功, == 服務(wù)器已經(jīng)成功連接
bufferevent_socket_connect(bufev, (struct sockaddr*)&addr, sizeof(addr));
// 3. 通信
// 給bufferevent的緩沖區(qū)設(shè)置回調(diào)
bufferevent_setcb(bufev, read_cb, write_cb, events_cb, (void*)"hello, world");
bufferevent_enable(bufev, EV_READ);
// 創(chuàng)建一個(gè)普通的輸入事件
struct event* myev = event_new(base, STDIN_FILENO, EV_READ|EV_PERSIST, send_msg, bufev);
event_add(myev, NULL);
event_base_dispatch(base);
event_free(myev);
event_base_free(base);
return 0;
}
8. 總結(jié):
處理不帶緩沖區(qū)的事件:
- 創(chuàng)建事件處理框架event_base event_base_new()
- 創(chuàng)建新事件event event_new()
- 將事件添加到事件處理框架event_base上 event_add()
- 啟動(dòng)事件循環(huán)檢測 event_base_dispatch()
- 循環(huán)結(jié)束之后釋放資源 event_base_free() 、event_free()
處理帶緩沖區(qū)的事件:
1、創(chuàng)建事件處理框架event_base event_base_new()
2、服務(wù)器端:
- 創(chuàng)建連接監(jiān)聽器(在回調(diào)函數(shù)得到fd) evconnlistener_new_bind()
- 將通信fd包裝 bufferevent_socket_new()
- 使用bufferevent通信:給bufferevent讀寫緩沖區(qū)設(shè)置回調(diào)函數(shù) bufferevent_setcb()
- 設(shè)置讀緩沖區(qū)可用 bufferevent_enable()
- 對(duì)緩沖區(qū)數(shù)據(jù)操作 bufferevent_write()、bufferevent_rea()
3、客戶端:
- 創(chuàng)建通信用的fd并且使用bufferevent包裝 bufferevent_socket_new()
- 連接服務(wù)器 bufferevent_socket_connect()
- 使用bufferevent通信:給bufferevent讀寫緩沖區(qū)設(shè)置回調(diào)函數(shù) bufferevent_setcb()
- 設(shè)置讀緩沖區(qū)可用 bufferevent_enable()
- 對(duì)緩沖區(qū)數(shù)據(jù)操作 bufferevent_write()、bufferevent_read()
-
C語言
+關(guān)注
關(guān)注
180文章
7595瀏覽量
135892 -
源碼
+關(guān)注
關(guān)注
8文章
632瀏覽量
29112 -
網(wǎng)絡(luò)庫
+關(guān)注
關(guān)注
0文章
7瀏覽量
1284
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論