1、创建底座
event_base_new()
2、创建监听器 相当于socket() bind() listen() accept()
evconnlistener_new_bind(, listencb,)
3、一旦监听器满足, 自动回调监听器对应的回调函数, (有cfd通信套接字)
listencb(, cfd, clientaddr, );
4、在listencb内新建1个带缓冲区的事件bufferevent
bufferevent_socket_new(, cfd, BEV_OPT_CLOSE_ON_FREE);
5、设置bufferevent事件的读、写缓冲区对应的回调函数
bufferevent_setcb(,readcb, writecb,);(相当于把事件添加到底座上)
读缓冲区内有数据 = 自动回调readcb = 客户端发数据了, 服务器处理数据并回发
写缓冲区内有数据 = 自动写给对端, 写完调writecb(鸡肋 = 传NULL)
6、开启bufferevent的读缓冲区(新bufferevent事件默认关闭)
bufferevent_ebable(, EV_READ); 结束填充istencb函数
7、循环监听
event_base_dispatch();
8、一旦(监听器)事件满足回调readcb读客户端数据、处理数据
9、释放底座、释放监听器
evconnlistener_free()
event_base_free()
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <event2/event.h> // 创建底座 普通事件等用的
#include <event2/bufferevent.h> // 创建带缓冲区的事件用的
#include <event2/listener.h> // 创建监听器用的
// 读缓冲的回调函数(读缓冲区有数据 = 自动回调)
// 8、读缓冲的回调函数, 处理数据发给客户端
void readcb(struct bufferevent * bev, void *ctx)
{
char buf[BUFSIZ];
size_t n; // 读到的字节数
// 读数据(带缓冲区的事件封装了cfd)
n = bufferevent_read(bev, buf, BUFSIZ);
// 小写转大写
for (int i = 0; i < n; ++i)
buf[i] = toupper(buf[i]);
// 写回去(带缓冲区的事件封装了cfd)
bufferevent_write(bev, buf, n);
}
// 试试鸡肋的写缓冲区的回调函数(写缓冲的数据写给了对方, 才回调鸡肋)
void writecb(struct bufferevent * bev, void *ctx)
{
printf("server received your data\n");
}
// 监听器的回调函数
void listencb(struct evconnlistener *listener, evutil_socket_t sockfd, struct sockaddr *addr, int len, void *ptr)
{
// 说明客户端建立连接, 准备读客户端发来的数据
struct event_base * base = (struct event_base *)ptr; // 接收传参
// 4、创建1个带缓冲区的事件
struct bufferevent *bev = NULL;
bev = bufferevent_socket_new(base, sockfd, BEV_OPT_CLOSE_ON_FREE); // 需要封装fd(通信套接字)
// 5、给bev读缓冲区和写缓冲区设置回调函数 = (读缓冲区有数据 = 自动回调)
bufferevent_setcb(bev, readcb, writecb, NULL, bev); // 把事件传参进去
// 6、开启bufferevent的读缓冲区(读缓冲默认关闭)
bufferevent_enable(bev, EV_READ);
}
int main(void)
{
// 服务器ip + 端口号
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(9527);
// 1、创建1个底座
struct event_base *base = NULL;
base = event_base_new();
// 2、创建1个监听器(监听客户端连接事件)
struct evconnlistener *evlistener = NULL;
evlistener = evconnlistener_new_bind(base, listencb, base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 128,
(struct sockaddr *)&saddr, sizeof(saddr)); // 给回调函数传参 base
// 3、封装listencb回调函数, 一旦客户端连接, 自动回调listenecb, 获得cfd(通信套接字), 连接的客户端的信息(ip + 端口号)
// 7、循环监听event_base_dispatch监听器事件是否满足, 一旦满足执行listencd回调函数
event_base_dispatch(base);
// 9、销毁监听器 销毁底座
evconnlistener_free(evlistener);
event_base_free(base);
return 0;
}
(二)、nc 127.0.0.1 9527测试(并发)
![](https://i-blog.csdnimg.cn/blog_migrate/ed9aebf4115f21216926c2378a9dc236.png)