Libevent实现server的三种方法,原生socket event 、bufferevent 、evconnlistener

编程入门 行业动态 更新时间:2024-10-19 17:21:50

Libevent实现server的<a href=https://www.elefans.com/category/jswz/34/1770022.html style=三种方法,原生socket event 、bufferevent 、evconnlistener"/>

Libevent实现server的三种方法,原生socket event 、bufferevent 、evconnlistener

参考文章
可以用上篇文章的poll client进行测试

bufferevent 帮我们更好的处理单纯的读写操作
evconnlistener_new_bind内部帮我们使用了socket的accept bind等函数
带有定时器超过时间没有读写操作就将断开连接。
bufferevent_set_timeouts

#include <iostream>
#include <curl/curl.h>
#include <assert.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
#include <event2/thread.h>
#include <sys/types.h>
#include <error.h>
#include <unistd.h>
#include <string.h>void event_cb(struct bufferevent* bev, short event, void * arg )
{if ( event & BEV_EVENT_TIMEOUT )printf("client timeout\n");else if ( event & BEV_EVENT_EOF )printf("connection closed\n");else if ( event & BEV_EVENT_ERROR )printf("some other error\n");bufferevent_free(bev);
}void socket_read_cb(struct bufferevent* bev, void *arg)
{char msg[4096];size_t len = bufferevent_read(bev,msg,sizeof(msg));msg[len] = '\0';printf("recv the client msg: %s\n",msg);char reply_msg[4096] = " received the msg : ";strcat(reply_msg+ strlen(reply_msg),msg);bufferevent_write(bev,reply_msg, strlen(reply_msg));
}void listener_cb(struct evconnlistener *listener, evutil_socket_t fd,struct sockaddr*sock, int socklen, void*arg)
{printf("accapt a client %d \n",fd);struct event_base* base = (struct event_base *)arg;struct bufferevent *bev = bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev,socket_read_cb,NULL,event_cb,NULL);bufferevent_enable(bev,EV_READ | EV_PERSIST);struct timeval tv = {10,0};bufferevent_set_timeouts (bev, &tv, 0);
}typedef struct sockaddr SA;
int tcp_server_init(int port, int listen_num)
{int errno_save;evutil_socket_t listener;listener = ::socket(AF_INET, SOCK_STREAM, 0);if( listener == -1 )return -1;//允许多次绑定同一个地址。要用在socket和bind之间evutil_make_listen_socket_reuseable(listener);struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.s_addr = 0;sin.sin_port = htons(port);if( ::bind(listener, (SA*)&sin, sizeof(sin)) < 0 )goto error;if( ::listen(listener, listen_num) < 0)goto error;//跨平台统一接口,将套接字设置为非阻塞状态evutil_make_socket_nonblocking(listener);return listener;error:errno_save = errno;evutil_closesocket(listener);errno = errno_save;return -1;
}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);}int sockfd = *((int*)arg);//把终端的消息发送给服务器端//为了简单起见,不考虑写一半数据的情况write(sockfd, msg, ret);
}void socket_read_cb(int fd , short  events , void * arg )
{char msg[4096];int len = read(fd, msg, sizeof(msg) - 1);if(len <= 0){printf("some error happen when read\n");return;}msg[len] = '\0';printf("recv the client msg : %s\n", msg);
}void accept_cb(int fd , short events , void * arg )
{evutil_socket_t sockfd;struct sockaddr_in client;socklen_t len = sizeof(client);sockfd = ::accept(fd, (struct sockaddr*)&client, &len);evutil_make_socket_nonblocking(sockfd);printf("accept a client %d\n", sockfd);struct event_base* base = (event_base*)arg;/** 很堵,被STDIN堵住了//动态创建一个event结构体,并将其作为回调参数传递给struct event* ev2 = event_new(NULL, -1, 0, NULL, NULL);struct event* ev = event_new(NULL, -1, 0, NULL, NULL);event_assign(ev2, base, STDIN_FILENO, EV_WRITE  | EV_PERSIST, cmd_msg_cb, (void *)&sockfd);event_assign(ev, base, sockfd, EV_READ | EV_PERSIST, socket_read_cb, NULL);event_add(ev, NULL);event_add(ev2,NULL);*/struct bufferevent* bev = bufferevent_socket_new(base,sockfd,BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev,socket_read_cb,NULL, event_cb,arg);bufferevent_enable(bev,EV_READ );
}int main() {/*int listener = tcp_server_init(5000,10);assert(listener != -1 );struct event_base *base = event_base_new();assert(base != NULL);//creatfifo((void*)base);struct event* listen_event;listen_event = event_new(base,listener,EV_READ|EV_WRITE|EV_PERSIST,accept_cb,(void*)base);*/struct sockaddr_in sin ;memset(&sin,0,sizeof(struct  sockaddr_in));sin.sin_family = AF_INET;sin.sin_port = htons(5000);struct  event_base *base = event_base_new();struct evconnlistener * listener = evconnlistener_new_bind(base,listener_cb,base,LEV_OPT_CLOSE_ON_FREE, 10,(struct sockaddr *)&sin, sizeof(struct sockaddr_in));//监听终端输入事件event_base_dispatch(base);evconnlistener_free(listener);event_base_free(base);return 0;}

更多推荐

Libevent实现server的三种方法,原生socket event 、bufferevent 、evconnlistener

本文发布于:2023-11-30 14:37:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1651308.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:三种   方法   server   Libevent   evconnlistener

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!