bufferevent中函数作用及代码实现

bufferevent主要函数的作用

bufferevent_socket_new()
在应用程序中创建一个基于套接字的 bufferevent 结构体。用于封装底层网络操作、实现异步读写、管理缓冲区,并简化网络编程。
bufferevent_read()
从底层的套接字缓冲区中读取数据,并将其复制到应用层的缓冲区中
bufferevent_write()
将应用程序提供的数据写入到缓冲区中,以便后续发送给底层的网络连接或文件描述符等。
bufferevent_socket_connect()
是在应用程序中发起与远程主机的连接,并创建一个基于套接字的 bufferevent 结构体,以便后续的异步数据读写操作。

简易版代码实现
//bufferevent建立客户端的过程
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/util.h>

int tcp_connect_server(const char* server_ip, int port);
void cmd_msg_cb(int fd, short events, void* arg);
void server_msg_cb(struct bufferevent* bev, void* arg);
void event_cb(struct bufferevent* bev, short event, void* arg);

int main(int argc, char** argv)
{
    if (argc < 3)
    {
        //两个参数依次是服务器端的IP地址、端口号
        printf("please input 2 parameter\n");
        return -1;
    }
    //创建根节点
    struct event_base* base = event_base_new();
    //创建并且初始化buffer缓冲区
    //BEV_OPT_CLOSE_ON_FREE释放bufferevent自动关闭底层接口
    struct bufferevent* bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
	//event_new()初始化上树节点
    //监听终端输入事件 设置标准输入的监控,设置回调是 cmd_msg_cb 
    struct event* ev_cmd = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST, cmd_msg_cb, (void*)bev);
    //上树 开始监听标准输入的读事件
    event_add(ev_cmd, NULL);

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    //将ip地址转换为网络字节序
    inet_aton(argv[1], &server_addr.sin_addr);

    //连接到 服务器ip地址和端口 初始化了 socket文件描述符 socket+connect 
    bufferevent_socket_connect(bev, (struct sockaddr*)&server_addr, sizeof(server_addr));

    //设置buffer的回调函数 主要设置了读回调: server_msg_cb ,传入参数是标准输入的读事件
    //event_cb异常回调
    bufferevent_setcb(bev, server_msg_cb, NULL, event_cb, (void*)ev_cmd);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);
   
    //循环等待
    event_base_dispatch(base);
    event_free(ev_cmd);
    bufferevent_free(bev);
    event_base_free(base);
    printf("finished \n");
    return 0;
}
//终端输入回调
void cmd_msg_cb(int fd, short events, void* arg)
{
    char msg[1024];

    int ret = read(fd, msg, sizeof(msg));
    if (ret < 0)
    {
        perror("read fail ");
        exit(1);
    }
    //得到bufferevent指针,目的是为了写到bufferevent的写缓冲区
    struct bufferevent* bev = (struct bufferevent*)arg;

    //把终端的消息发送给服务器端
    //将msg的数据写到bufferevent的写缓冲区
    bufferevent_write(bev, msg, ret);
}
//读回调
void server_msg_cb(struct bufferevent* bev, void* arg)
{
    char msg[1024];
    //将bufferevent 读缓冲区的数据,读到msg中
    size_t len = bufferevent_read(bev, msg, sizeof(msg));
    msg[len] = '\0';
    printf("recv %s from server\n", msg);
}
//异常回调
void event_cb(struct bufferevent* bev, short event, void* arg)
{
    //对方关闭连接
    if (event & BEV_EVENT_EOF)
        printf("connection closed\n");
    //出错
    else if (event & BEV_EVENT_ERROR)
        printf("some other error\n");
    //建立连接成功
    else if (event & BEV_EVENT_CONNECTED)
    {
        printf("the client has connected to server\n");
        return;
    }
    //这将自动close套接字和free读写缓冲区
    bufferevent_free(bev);
    //释放event事件 监控读终端
    struct event* ev = (struct event*)arg;
    event_free(ev);
    exit(0);
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于libevent实现的WebSocket客户端的示例代码: ``` #include <event2/event.h> #include <event2/buffer.h> #include <event2/http.h> #include <event2/http_struct.h> #include <event2/keyvalq_struct.h> #include <event2/bufferevent_ssl.h> #include <openssl/ssl.h> #include <openssl/err.h> static void websocket_readcb(struct bufferevent *bev, void *ctx); static void websocket_eventcb(struct bufferevent *bev, short events, void *ctx); int main(int argc, char **argv) { struct event_base *base; struct bufferevent *bev; struct sockaddr_in sin; SSL_CTX *ssl_ctx; SSL *ssl; base = event_base_new(); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_port = htons(8080); bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, websocket_readcb, NULL, websocket_eventcb, NULL); bufferevent_enable(bev, EV_READ | EV_WRITE); bufferevent_socket_connect(bev, (struct sockaddr *)&sin, sizeof(sin)); ssl_ctx = SSL_CTX_new(TLSv1_2_client_method()); ssl = SSL_new(ssl_ctx); bufferevent_openssl_set_ssl(bev, ssl, BUFFEREVENT_SSL_CONNECTING); bufferevent_openssl_set_allow_dirty_shutdown(bev, 1); SSL_set_tlsext_host_name(ssl, "localhost"); // 发送WebSocket握手请求 char request[1024]; sprintf(request, "GET /websocket HTTP/1.1\r\n" "Host: localhost:8080\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n" "Sec-WebSocket-Version: 13\r\n" "\r\n"); bufferevent_write(bev, request, strlen(request)); event_base_dispatch(base); SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ssl_ctx); bufferevent_free(bev); event_base_free(base); return 0; } static void websocket_readcb(struct bufferevent *bev, void *ctx) { struct evbuffer *input = bufferevent_get_input(bev); char *line = NULL; size_t len = 0; ssize_t nread; while ((nread = evbuffer_get_line(input, &line, &len, EVBUFFER_EOL_CRLF)) > 0) { printf("%s\n", line); free(line); } } static void websocket_eventcb(struct bufferevent *bev, short events, void *ctx) { if (events & BEV_EVENT_CONNECTED) { printf("Connected.\n"); } else if (events & BEV_EVENT_ERROR) { printf("Error.\n"); } else if (events & BEV_EVENT_EOF) { printf("Connection closed.\n"); event_base_loopbreak(bufferevent_get_base(bev)); } } ``` 这个示例代码,首先创建了一个event_base对象,然后创建了一个bufferevent对象,并设置了回调函数。接着,使用bufferevent_socket_connect函数连接到WebSocket服务器,然后创建了一个SSL_CTX对象和一个SSL对象,并使用bufferevent_openssl_set_ssl函数将SSL对象关联到bufferevent对象上。接下来,发送了一个WebSocket握手请求。最后,调用event_base_dispatch函数进入事件循环。 在事件循环,如果接收到了数据,就调用websocket_readcb函数进行处理。如果连接建立成功,就输出Connected。如果发生错误,就输出Error。如果连接关闭,就输出Connection closed,并调用event_base_loopbreak函数退出事件循环。 需要注意的是,这个示例代码使用了OpenSSL库,所以需要链接libssl和libcrypto库。在Linux系统,可以使用以下命令编译: ``` $ gcc -o websocket-client websocket-client.c -levent -lssl -lcrypto ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值