Libevent库基础(2)
带缓冲区的事件 bufferevent
#include <event2/bufferevent.h>
read/write 两个缓冲. 借助 队列.
创建、销毁bufferevent:
struct bufferevent *ev;
struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, enum bufferevent_options options);
base: event_base
fd: 封装到bufferevent内的 fd
options:BEV_OPT_CLOSE_ON_FREE
返回: 成功创建的 bufferevent事件对象。
void bufferevent_socket_free(struct bufferevent *ev);
给bufferevent设置回调:
对比event: event_new( fd, callback ); event_add() -- 挂到 event_base 上。
bufferevent_socket_new(fd) bufferevent_setcb( callback )
void bufferevent_setcb(struct bufferevent * bufev,
bufferevent_data_cb readcb,
bufferevent_data_cb writecb,
bufferevent_event_cb eventcb,
void *cbarg );
bufev: bufferevent_socket_new() 返回值
readcb: 设置 bufferevent 读缓冲,对应回调 read_cb{ bufferevent_read() 读数据 }
writecb: 设置 bufferevent 写缓冲,对应回调 write_cb { } -- 给调用者,发送写成功通知。 可以 NULL
eventcb: 设置 事件回调。 也可传NULL
typedef void (*bufferevent_event_cb)(struct bufferevent *bev, short events, void *ctx);
void event_cb(struct bufferevent *bev, short events, void *ctx)
{
。。。。。
}
events: BEV_EVENT_CONNECTED
cbarg: 上述回调函数使用的 参数。
read 回调函数类型:
typedef void (*bufferevent_data_cb)(struct bufferevent *bev, void*ctx);
void read_cb(struct bufferevent *bev, void *cbarg )
{
.....
bufferevent_read(); --- read();
}
bufferevent_read()函数的原型:
size_t bufferevent_read(struct bufferevent *bev, void *buf, size_t bufsize);
write 回调函数类型:
int bufferevent_write(struct bufferevent *bufev, const void *data, size_t size);
启动、关闭 bufferevent的 缓冲区:
void bufferevent_enable(struct bufferevent *bufev, short events); 启动
events: EV_READ、EV_WRITE、EV_READ|EV_WRITE
默认、write 缓冲是 enable、read 缓冲是 disable
bufferevent_enable(evev, EV_READ); -- 开启读缓冲
连接客户端:
socket();connect();
int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen);
bev: bufferevent 事件对象(封装了fd)
address、len:等同于 connect() 参2/3
创建监听服务器:
------ socket();bind();listen();accept();
struct evconnlistener * listner;
struct evconnlistener *evconnlistener_new_bind (
struct event_base *base,
evconnlistener_cb cb,
void *ptr,
unsigned flags,
int backlog,
const struct sockaddr *sa,
int socklen);
base: event_base
cb: 回调函数。 一旦被回调,说明在其内部应该与客户端完成, 数据读写操作,进行通信。
ptr: 回调函数的参数
flags: LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE
backlog: listen() 2参。 -1 表最大值
sa:服务器自己的地址结构体
socklen:服务器自己的地址结构体大小。
返回值:成功创建的监听器。
释放监听服务器:
void evconnlistener_free(struct evconnlistener *lev);
服务器端 libevent 创建TCP连接:
1. 创建event_base
2. 创建bufferevent事件对象。bufferevent_socket_new();
3. 使用bufferevent_setcb() 函数给 bufferevent的 read、write、event 设置回调函数。
4. 当监听的 事件满足时,read_cb会被调用, 在其内部 bufferevent_read();读
5. 使用 evconnlistener_new_bind 创建监听服务器, 设置其回调函数,当有客户端成功连接时,这个回调函数会被调用。
6. 封装 listner_cb() 在函数内部。完成与客户端通信
7. 设置读缓冲、写缓冲的 使能状态 enable、disable
8.启动循环 event_base_dispath();
9.释放连接
客户端端 libevent 创建TCP连接:
1、event_base
2. 创建bufferevent事件对象。bufferevent_socket_new();
3、bufferevent_socket_connect()连接服务器
4、使用bufferevent_setcb()函数给 bufferevent的 read、write、event 设置回调函数
5、设置读缓冲、写缓冲的 使能状态 enable、disable
6、接收和发送数据bufferevent_read()/bufferevent_write()
7、启动循环 event_base_dispath();
8、释放连接
libevent的服务器代码:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <string.h>
7 #include <event2/event.h>
8 #include <event2/listener.h>
9 #include <event2/bufferevent.h>
10
11 // 读缓冲区回调
12 void read_cb(struct bufferevent *bev, void *arg)
13 {
14 char buf[1024] = {0};
15 bufferevent_read(bev, buf, sizeof(buf));
16 printf("client say: %s\n", buf);
17
18 char *p = "我是服务器, 已经成功收到你发送的数据!";
19 // 发数据给客户端
20 bufferevent_write(bev, p, strlen(p)+1);
21 sleep(1);
22 }
23
24 // 写缓冲区回调
25 void write_cb(struct bufferevent *bev, void *arg)
26 {
27 printf("I'm服务器, 成功写数据给客户端,写缓冲区回调函数被回调...\n");
28 }
29
30 // 事件
31 void event_cb(struct bufferevent *bev, short events, void *arg)
32 {
33 if (events & BEV_EVENT_EOF)
34 {
35 printf("connection closed\n");
36 }
37 else if(events & BEV_EVENT_ERROR)
38 {
39 printf("some other error\n");
40 }
41
42 bufferevent_free(bev);
43 printf("buffevent 资源已经被释放...\n");
44 }
45
46
47
48 void cb_listener(
49 struct evconnlistener *listener,
50 evutil_socket_t fd,
51 struct sockaddr *addr,
52 int len, void *ptr)
53 {
54 printf("connect new client\n");
55
56 struct event_base* base = (struct event_base*)ptr;
57 // 通信操作
58 // 添加新事件
59 struct bufferevent *bev;
60 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
61
62 // 给bufferevent缓冲区设置回调
63 bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
64 bufferevent_enable(bev, EV_READ);
65 }
66
67
68 int main(int argc, const char* argv[])
69 {
70
71 // init server
72 struct sockaddr_in serv;
73
74 memset(&serv, 0, sizeof(serv));
75 serv.sin_family = AF_INET;
76 serv.sin_port = htons(9876);
77 serv.sin_addr.s_addr = htonl(INADDR_ANY);
78
79 struct event_base* base;
80 base = event_base_new();
81 // 创建套接字
82 // 绑定
83 // 接收连接请求
84 struct evconnlistener* listener;
85 listener = evconnlistener_new_bind(base, cb_listener, base,
86 LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
87 36, (struct sockaddr*)&serv, sizeof(serv));
88
89 event_base_dispatch(base);
90
91 evconnlistener_free(listener);
92 event_base_free(base);
93
94 return 0;
95 }
libevent客户端代码:
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <string.h>
7 #include <event2/bufferevent.h>
8 #include <event2/event.h>
9 #include <arpa/inet.h>
10
11 void read_cb(struct bufferevent *bev, void *arg)
12 {
13 char buf[1024] = {0};
14 bufferevent_read(bev, buf, sizeof(buf));
15
16 printf("fwq say:%s\n", buf);
17
18 bufferevent_write(bev, buf, strlen(buf)+1);
19 sleep(1);
20 }
21
22 void write_cb(struct bufferevent *bev, void *arg)
23 {
24 printf("----------我是客户端的写回调函数,没卵用\n");
25 }
26
27 void event_cb(struct bufferevent *bev, short events, void *arg)
28 {
29 if (events & BEV_EVENT_EOF)
30 {
31 printf("connection closed\n");
32 }
33 else if(events & BEV_EVENT_ERROR)
34 {
35 printf("some other error\n");
36 }
37 else if(events & BEV_EVENT_CONNECTED)
38 {
39 printf("已经连接服务器...\\(^o^)/...\n");
40 return;
41 }
42
43 // 释放资源
44 bufferevent_free(bev);
45 }
46
47 // 客户端与用户交互,从终端读取数据写给服务器
48 void read_terminal(evutil_socket_t fd, short what, void *arg)
49 {
50 // 读数据
51 char buf[1024] = {0};
52 int len = read(fd, buf, sizeof(buf));
53
54 struct bufferevent* bev = (struct bufferevent*)arg;
55 // 发送数据
56 bufferevent_write(bev, buf, len+1);
57 }
58
59 int main(int argc, const char* argv[])
60 {
61 struct event_base* base = NULL;
62 base = event_base_new();
63
64 int fd = socket(AF_INET, SOCK_STREAM, 0);
65
66 // 通信的fd放到bufferevent中
67 struct bufferevent* bev = NULL;
68 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
69
70 // init server info
71 struct sockaddr_in serv;
72 memset(&serv, 0, sizeof(serv));
73 serv.sin_family = AF_INET;
74 serv.sin_port = htons(9876);
75 inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
76
77 // 连接服务器
78 bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));
79
80 // 设置回调
81 bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
82
83 // 设置读回调生效
84 // bufferevent_enable(bev, EV_READ);
85
86 // 创建事件
87 struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST,
88 read_terminal, bev);
89 // 添加事件
90 event_add(ev, NULL);
91
92 event_base_dispatch(base);
93
94 event_free(ev);
95
96 event_base_free(base);
97
98 return 0;
99 }
Libevent库基础(2)的更多相关文章
- Libevent库基础(1)
1.创建 eevent_base struct event_base *base = event_base_new(); 2.创建 事件event struct event *ev; struct e ...
- Libevent库学习笔记
Libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,Libevent在底层select.pool.kqueue和epoll等机制基础上,封装出一致的事件接口.可 ...
- libevent库介绍--事件和数据缓冲
首先在学习libevent库的使用前,我们还要从基本的了解开始,已经熟悉了epoll以及reactor,然后从event_base学习,依次学习事件event.数据缓冲Bufferevent和数据封装 ...
- Windows平台下libevent库的使用
1 引子 手头上有一个使用了4个年头的HttpClient库,自己封装的,对于集成了IE浏览器的应用程序很友好.但最近想把产品扩展到Chrome和FireFox阵营,萌发了重构HttpClie ...
- C10K问题和Libevent库介绍
http://blog.chinaunix.net/uid-20761674-id-75056.html 一.C10K的问题 C10K的问题在上个世纪90年代就被提出来了.大概的意思是当用户数超过1万 ...
- R1:创建Libevent库
原文链接:http://www.wangafu.net/~nickm/libevent-book/Ref1_libsetup.html Setting up the Libevent library ...
- python linecache标准库基础学习
#python标准库基础之:linecacge:高效读取文本文件#说明与作用"""可以从文件或者导入python模块获取文件,维护一个结果缓存,从而可以更高效地从相同文件 ...
- C 标准库基础 IO 操作总结
其实输入与输出对于不管什么系统的设计都是异常重要的,比如设计 C 接口函数,首先要设计好输入参数.输出参数和返回值,接下来才能开始设计具体的实现过程.C 语言标准库提供的接口功能很有限,不像 Pyth ...
- libevent库简单使用
一.libevent库简介 Libevent是一个用于开发可扩展性网络服务器的基于事件驱动(event-driven)模型的网络库.Libevent有几个显著的亮点: (1)事件驱动(event-dr ...
随机推荐
- NLP常见任务
借助BERT论文, 梳理下自然语言处理当前常见的任务. NLP任务 根据判断主题的级别, 将所有的NLP任务分为两种类型: token-level task: token级别的任务. 如完形填空(Cl ...
- iOS14剪切板探究,淘宝实现方法分析
随着iOS 14的发布,剪切板的滥用也被大家所知晓.只要是APP读取剪切板内容,系统都会在顶部弹出提醒,而且这个提醒不能够关闭.这样,大家在使用APP的过程中就能够看到哪些APP使用了剪切板. 正好我 ...
- 适用于 deno 的多版本管理工具 dvm 发布
不知不觉中,deno 已经默默的发布了 3 个版本了: 0.1.0 0.1.1 0.1.2 昨晚通宵做了一个 deno 多版本的管理工具: dvm. github 地址: https://github ...
- MySQL 8.0索引合并
简介 参考https://dev.mysql.com/doc/refman/8.0/en/index-merge-optimization.html#index-merge-intersection. ...
- 手把手撸套框架-Victory框架1.0 详解
目录 其实Victory框架1.0 在8月份就完成了,整个9月份都没有更新博客,主要还是因为松懈了. 所以,趁着国庆节的放假的时间把博客给更新一下,1.0总的来说算不得一个成熟的产品,但是拿来开发我们 ...
- Book of Shaders 04 - 网格噪声:Worley Noise
0x00 思路 假设要生成 4 个网格,可以先在空间中指定 4 个特征点.对于每个像素点,计算它到最近特征点的距离,将这个距离当作结果值输出. #ifdef GL_ES precision mediu ...
- 022 01 Android 零基础入门 01 Java基础语法 03 Java运算符 02 算术运算符
022 01 Android 零基础入门 01 Java基础语法 03 Java运算符 02 算术运算符 本文知识点:Java中的算术运算符 算术运算符介绍 算术运算符代码示例 注意字符串连接问题和整 ...
- np.random.multivariate_normal方法浅析
从多元正态分布中抽取随机样本. 多元正态分布,多正态分布或高斯分布是一维正态分布向更高维度的推广.这种分布由其均值和协方差矩阵来确定.这些参数类似于一维正态分布的平均值(平均值或"中心&qu ...
- VSCODE 配置eslint规则和自动修复
全局安装eslint 打开终端,运行npm install eslint -g全局安装ESLint. vscode安装插件 vscode 扩展设置 依次点击 文件 > 首选项 > 设置 { ...
- dirsearch下载与简单实用
下载 下载地址 我的电脑是Windows,而且我也有python3.6的环境,所以我是直接clone到本地就能使用了. 命令的提示在上面的下载地址里就有,这里给个最简单的命令(脚本小子专属,我 ...