栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

高性能I/O框架库Libevent

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

高性能I/O框架库Libevent

Libevent
  • Linux服务器程序处理的三类事件
  • I/O框架库的组件
  • Libevent支持的事件类型:
  • 代码实现
    • 客户端
    • 服务器

Linux服务器程序处理的三类事件

I/O事件、信号事件和定时事件。

I/O框架库以库函数的形式,封装了较为底层的系统调用。

I/O框架库的组件

基于Reactor模式的I/O框架库包含的组件:句柄、事件多路分发器、事件处理器和具体的事件处理器。

  1. 句柄
    I/O框架库要处理的对象,即I/O事件、信号事件和定时事件,统一称为事件源。
    I/O事件对应的句柄是文件描述符,信号事件对应的句柄是信号值。

  2. 事件多路分发器
    即事件循环。内部调用的是select、poll、epoll_wait.

  3. 事件处理器和具体事件处理器

  1. 定义实例;
  2. 创建事件;
  3. 注册(添加)到libevent;
  4. 事件循环;
Libevent支持的事件类型:

代码实现
  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 
  9 void sig_cb(int fd,short ev,void*arg)//回调函数
 10 {
 11     printf("sig=%dn",fd);
 12 }
 13 void time_cb(int fd,short ev,void*arg)
 14 {
 15     printf("time outn");
 16 }
 17 int main()
 18 {
 19     struct event_base*base=event_init();//定义一个实例(libevent) 框架
 20     assert(base!=NULL);
 21 
 22    struct event*sig_ev=evsignal_new(base,SIGINT,sig_cb,NULL); //定义信号事>    件
 23    assert(sig_ev!=NULL);
 24 
 25    event_add(sig_ev,NULL);//添加(注册)事件到libevent实例
 26 
 27    struct timeval tv={5,0};
 28    struct event*time_ev=evtimer_new(base,time_cb,NULL);//定义定时事件
 29    assert(time_ev!=NULL);
 30    event_add(time_ev,&tv);//设置(添加)超时事件
 31 
 32   event_base_dispatch(base); //启动事件循环
 33 
 34   event_free(sig_ev);
 35   event_free(time_ev);
 36   event_base_free(base);
 37 
 38   exit(0);
 39 }                    

编译时,注意连接库,加上 -levent。


通过Libevent 检测多个客户端连接
自动调用I/O函数处理并发事件

客户端
#include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 
 10 int main()
 11 {
 12     int sockfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
 13     assert(sockfd!=-1);
 14 
 15     //bind()//可以绑定,但是一般不绑定
 16 
 17     struct sockaddr_in saddr;
 18     memset(&saddr,0,sizeof(saddr));
 19     saddr.sin_family=AF_INET;
 20     saddr.sin_port=htons(6000);
 21     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
 22 
 23     int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//三次握手
 24     assert(res!=-1);
 25     while(1)
 26     {
 27         char buff[128]={0};
 28         printf("input:n");
 29         fgets(buff,128,stdin);
 30 
 31         if(strncmp(buff,"end",3)==0)
 32         {
 33             break;
 34         }
 35         send(sockfd,buff,strlen(buff),0);
 36 
 37         memset(buff,0,128);
 38         recv(sockfd,buff,127,0);
 39         printf("buff=%sn",buff);
 40     }
 41     close(sockfd);
 42 }

服务器
  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8 #include
  9 #include
 10 
 11 void recv_cb(int fd,short ev,void*arg)
 12 {
 13     if(ev&EV_READ)
 14     {
 15         char buff[128]={0};
 16         int n=recv(fd,buff,127,0);
 17         if(n<=0)
 18         {
 19             struct event**p_cev=(struct event**)arg;
 20             event_free(*p_cev);
 21             free(p_cev);
 23             close(fd);
 22             printf("cilent closen");
 23             return ;
 24         }
 25         printf("recv:%sn",buff);
 26 
 27         send(fd,"ok",2,0);//写事件就绪,不用注册写事件,直接send
 28     }
 29 }
 30 void accept_cb(int fd,short ev,void* arg)
 31 {
 32     struct event_base* base=(struct event_base*)arg;
 33     if(base==NULL)
 34     {
 35         return ;
 36     }
 37     if(ev&EV_READ)
 38     {
 39         struct sockaddr_in caddr;
 40         int len=sizeof(caddr);
 41         int c=accept(fd,(struct sockaddr*)&caddr,&len);//接受连接
 42         if(c<0)
 43         {
 44             return ;
 45         }
 46         printf("accept c=%dn",c);
 47         struct event**p_cev=(struct event**)malloc(sizeof(struct event*));
 48         if(p_cev==NULL)
 49         {
 50             return ;
 51         }
 52         *p_cev=event_new(base,c,EV_READ|EV_PERSIST,recv_cb,p_cev);//将c添加到libevent实例中
 53         //  struct event*c_ev=event_new(base,c,EV_READ|EV_PERSIST,recv_cb,base);
 54 
 55         if(*p_cev==NULL)
 56         {
 57             return ;
 58         }
 59         event_add(*p_cev,NULL);
 60     }
 61 
 62 }
 63 
 64 int socket_init();
 65 int main()
 66 {
 67     struct event_base*base=event_init();
 68     assert(base!=NULL);
 69 
 70     int sockfd=socket_init();
 71     assert(sockfd!=-1);
 72 
 73     struct event*sock_ev=event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,base);
 74     event_add(sock_ev,NULL);
 75 
 76     event_base_dispatch(base);//启动事件循环
 77     event_free(sock_ev);
 78     event_base_free(base);
 79 }
 80 
 81 int socket_init()
 82 {
 83     int sockfd=socket(AF_INET,SOCK_STREAM,0);//创建套接字
 84     if(sockfd==-1)
 85     {
 86         return -1;
 87     }
 88 
 89     struct sockaddr_in saddr;
 90     memset(&saddr,0,sizeof(saddr));
 91     saddr.sin_family=AF_INET;
 92     saddr.sin_port=htons(6000);
 93     saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
 94     int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//指定监听>    套接子使用的是本主机的端口
 95     if(res==-1)
 96     {
 97         return -1;
 98     }
 99 
100     res=listen(sockfd,5);
101     if(res==-1)
102     {
103         return -1;
104     }
105     return sockfd;
106 
107 }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/642075.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号