libevent库的使用-2实现TCP下的C/S模型-服务器端

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测试(并发)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪呈祥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值