💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 7.4 使用bufferevent 基于套接字的 bufferevent 是最简单的,它使用 libevent 的底层事件机制来检测底层网络套 接字是否已经就绪,可以进行读写操作,并且使用底层网络调用(如 readv 、 writev 、 WSASend、WSARecv)来发送和接收数据。 ## 7.4.1 创建基于套接字的bufferevent 可以使用 bufferevent_socket_new()创建基于套接字的 bufferevent。 ```cpp struct bufferevent *bufferevent_socket_new( struct event_base *base, evutil_socket_t fd, enum bufferevent_options options); ``` base 是 event_base,options 是表示 bufferevent 选项(BEV_OPT_CLOSE_ON_FREE 等) 的位掩码, fd是一个可选的表示套接字的文件描述符。如果想以后设置文件描述符,可以设置fd为-1。 成功时函数返回一个 bufferevent,失败则返回 NULL。 ## 7.4.2 在bufferevent上启动链接 ```cpp int bufferevent_socket_connect(struct bufferevent *bev, struct sockaddr *address, int addrlen); ``` address 和 addrlen 参数跟标准调用 connect()的参数相同。如果还没有为 bufferevent 设置套接字,调用函数将为其分配一个新的流套接字,并且设置为非阻塞的。 如果已经为 bufferevent 设置套接字,调用bufferevent_socket_connect() 将告知 libevent 套接字还未连接,直到连接成功之前不应该对其进行读取或者写入操作。 连接完成之前可以向输出缓冲区添加数据。 如果连接成功启动,函数返回 0;如果发生错误则返回 -1。 ```cpp #include <event2/event.h> #include <event2/bufferevent.h> #include <sys/socket.h> #include <string.h> void eventcb(struct bufferevent *bev, short events, void *ptr) { if (events & BEV_EVENT_CONNECTED) { /* We're connected to 127.0.0.1:8080. Ordinarily we'd do something here, like start reading or writing. */ } else if (events & BEV_EVENT_ERROR) { /* An error occured while connecting. */ } } int main_loop(void) { struct event_base *base; struct bufferevent *bev; struct sockaddr_in sin; base = event_base_new(); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ sin.sin_port = htons(8080); /* Port 8080 */ bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, NULL, NULL, eventcb, NULL); if (bufferevent_socket_connect(bev, (struct sockaddr *)&sin, sizeof(sin)) < 0) { /* Error starting connection */ bufferevent_free(bev); return -1; } event_base_dispatch(base); return 0; } ``` **`注意`:如果使用 bufferevent_socket_connect() 发起连接,将只会收 到 BEV_EVENT_CONNECTED 事件。如果自己调用 connect(),则连接上将被报告为写入事 件。**