zoukankan      html  css  js  c++  java
  • libevent源码分析-TCP服务端代码

    先贴一段代码再说,Linux下使用g++ -g-o server server.c -levent

    可以直接使用gdb调试,而且可以跟踪到libevent的库里。

      1 #include <stdio.h>    
      2 #include <string.h>    
      3 #include <iostream>    
      4 #include <sys/socket.h>        
      5 #include <netinet/in.h>        
      6 #include <arpa/inet.h>        
      7 #include <netdb.h>    
      8     
      9 #include <event.h>    
     10 using namespace std;    
     11     
     12 // 事件base    
     13 struct event_base* base;    
     14     
     15 // 读事件回调函数    
     16 void onRead(int iCliFd, short iEvent, void *arg)    
     17 {    
     18     int iLen;    
     19     char buf[1500];    
     20     
     21     iLen = recv(iCliFd, buf, 1500, 0);    
     22     
     23     if (iLen <= 0) {    
     24         cout << "Client Close" << endl;    
     25     
     26         // 连接结束(=0)或连接错误(<0),将事件删除并释放内存空间    
     27         struct event *pEvRead = (struct event*)arg;    
     28         event_del(pEvRead);    
     29         delete pEvRead;    
     30     
     31         close(iCliFd);    
     32         return;    
     33     }    
     34     
     35     buf[iLen] = 0;    
     36     cout << "Client Info:" << buf << endl;    
     37   
     38   
     39   
     40     struct bufferevent* buf_ev;  
     41     buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);  
     42     buf_ev->wm_read.high = 4096;  
     43     char MESSAGE[]="welcome to server..";  
     44     bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));  
     45 }    
     46     
     47 // 连接请求事件回调函数    
     48 void onAccept(int iSvrFd, short iEvent, void *arg)    
     49 {    
     50     int iCliFd;    
     51     struct sockaddr_in sCliAddr;    
     52     
     53     socklen_t iSinSize = sizeof(sCliAddr);    
     54     iCliFd = accept(iSvrFd, (struct sockaddr*)&sCliAddr, &iSinSize);    
     55     
     56     // 连接注册为新事件 (EV_PERSIST为事件触发后不默认删除)    
     57     struct event *pEvRead = new event;    
     58     event_set(pEvRead, iCliFd, EV_READ|EV_PERSIST, onRead, pEvRead);    
     59     event_base_set(base, pEvRead);    
     60     event_add(pEvRead, NULL);   
     61   
     62   
     63     struct bufferevent* buf_ev;    
     64      buf_ev = bufferevent_new(iCliFd, NULL, NULL, NULL, NULL);      
     65      buf_ev->wm_read.high = 4096;  
     66      char MESSAGE[]="welcome to server..";  
     67     bufferevent_write(buf_ev, MESSAGE, strlen(MESSAGE));   
     68   
     69     cout<<"a client connect:"<<iCliFd<<endl;  
     70 }    
     71     
     72 int main()    
     73 {    
     74     
     75     int iSvrFd;      
     76     struct sockaddr_in sSvrAddr;    
     77                   
     78     memset(&sSvrAddr, 0, sizeof(sSvrAddr));      
     79     sSvrAddr.sin_family = AF_INET;      
     80     sSvrAddr.sin_addr.s_addr = inet_addr("127.0.0.1");        
     81     sSvrAddr.sin_port = htons(8888);       
     82                                 
     83     // 创建tcpSocket(iSvrFd),监听本机8888端口      
     84     iSvrFd = socket(AF_INET, SOCK_STREAM, 0);      
     85     bind(iSvrFd, (struct sockaddr*)&sSvrAddr, sizeof(sSvrAddr));      
     86     listen(iSvrFd, 10);    
     87     
     88     // 初始化base    
     89     base = (struct event_base*)event_init();    
     90         
     91     struct event evListen;    
     92     // 设置事件    
     93     event_set(&evListen, iSvrFd, EV_READ|EV_PERSIST, onAccept, NULL);    
     94     // 设置为base事件    
     95     event_base_set(base, &evListen);    
     96     // 添加事件    
     97     event_add(&evListen, NULL);    
     98         
     99     // 事件循环    
    100     event_base_dispatch(base);    
    101     
    102     return 0;    
    103 }    
    View Code

    下面列出epoll服务端源码

      1 #include <iostream>
      2 #include <sys/socket.h>
      3 #include <sys/epoll.h>
      4 #include <netinet/in.h>
      5 #include <arpa/inet.h>
      6 #include <fcntl.h>
      7 #include <unistd.h>
      8 #include <stdio.h>
      9 #include <errno.h>
     10 
     11 using namespace std;
     12 
     13 #define MAXLINE 5
     14 #define OPEN_MAX 100
     15 #define LISTENQ 20
     16 #define SERV_PORT 5000
     17 #define INFTIM 1000
     18 
     19 void setnonblocking(int sock)
     20 {
     21     int opts;
     22     opts=fcntl(sock,F_GETFL);
     23     if(opts<0)
     24     {
     25         perror("fcntl(sock,GETFL)");
     26         exit(1);
     27     }
     28     opts = opts|O_NONBLOCK;
     29     if(fcntl(sock,F_SETFL,opts)<0)
     30     {
     31         perror("fcntl(sock,SETFL,opts)");
     32         exit(1);
     33     }
     34 }
     35 
     36 int main(int argc, char* argv[])
     37 {
     38     int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
     39     ssize_t n;
     40     char line[MAXLINE];
     41     socklen_t clilen;
     42 
     43 
     44     if ( 2 == argc )
     45     {
     46         if( (portnumber = atoi(argv[1])) < 0 )
     47         {
     48             fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
     49             return 1;
     50         }
     51     }
     52     else
     53     {
     54         fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
     55         return 1;
     56     }
     57 
     58 
     59 
     60     //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
     61 
     62     struct epoll_event ev,events[20];
     63     //生成用于处理accept的epoll专用的文件描述符
     64 
     65     epfd=epoll_create(256);
     66     struct sockaddr_in clientaddr;
     67     struct sockaddr_in serveraddr;
     68     listenfd = socket(AF_INET, SOCK_STREAM, 0);
     69     //把socket设置为非阻塞方式
     70 
     71     //setnonblocking(listenfd);
     72 
     73     //设置与要处理的事件相关的文件描述符
     74 
     75     ev.data.fd=listenfd;
     76     //设置要处理的事件类型
     77 
     78     ev.events=EPOLLIN|EPOLLET;
     79     //ev.events=EPOLLIN;
     80 
     81     //注册epoll事件
     82 
     83     epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
     84     bzero(&serveraddr, sizeof(serveraddr));
     85     serveraddr.sin_family = AF_INET;
     86     char *local_addr="127.0.0.1";
     87     inet_aton(local_addr,&(serveraddr.sin_addr));//htons(portnumber);
     88 
     89     serveraddr.sin_port=htons(portnumber);
     90     bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
     91     listen(listenfd, LISTENQ);
     92     maxi = 0;
     93     for ( ; ; ) {
     94         //等待epoll事件的发生
     95 
     96         nfds=epoll_wait(epfd,events,20,500);
     97         //处理所发生的所有事件
     98 
     99         for(i=0;i<nfds;++i)
    100         {
    101             if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
    102 
    103             {
    104                 connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
    105                 if(connfd<0){
    106                     perror("connfd<0");
    107                     exit(1);
    108                 }
    109                 //setnonblocking(connfd);
    110 
    111                 char *str = inet_ntoa(clientaddr.sin_addr);
    112                 cout << "accapt a connection from " << str << endl;
    113                 //设置用于读操作的文件描述符
    114 
    115                 ev.data.fd=connfd;
    116                 //设置用于注测的读操作事件
    117 
    118                 ev.events=EPOLLIN|EPOLLET;
    119                 //ev.events=EPOLLIN;
    120 
    121                 //注册ev
    122 
    123                 epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
    124             }
    125             else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
    126 
    127             {
    128                 cout << "EPOLLIN" << endl;
    129                 if ( (sockfd = events[i].data.fd) < 0)
    130                     continue;
    131                 if ( (n = read(sockfd, line, MAXLINE)) < 0) {
    132                     if (errno == ECONNRESET) {
    133                         close(sockfd);
    134                         events[i].data.fd = -1;
    135                     } else
    136                         std::cout<<"readline error"<<std::endl;
    137                 } else if (n == 0) {
    138                     close(sockfd);
    139                     events[i].data.fd = -1;
    140                 }
    141                 line[n] = '/0';
    142                 cout << "read " << line << endl;
    143                 //设置用于写操作的文件描述符
    144 
    145                 ev.data.fd=sockfd;
    146                 //设置用于注测的写操作事件
    147 
    148                 ev.events=EPOLLOUT|EPOLLET;
    149                 //修改sockfd上要处理的事件为EPOLLOUT
    150 
    151                 //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
    152 
    153             }
    154             else if(events[i].events&EPOLLOUT) // 如果有数据发送
    155 
    156             {
    157                 sockfd = events[i].data.fd;
    158                 write(sockfd, line, n);
    159                 //设置用于读操作的文件描述符
    160 
    161                 ev.data.fd=sockfd;
    162                 //设置用于注测的读操作事件
    163 
    164                 ev.events=EPOLLIN|EPOLLET;
    165                 //修改sockfd上要处理的事件为EPOLIN
    166 
    167                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
    168             }
    169         }
    170     }
    171     return 0;
    172 }
    View Code
  • 相关阅读:
    HDU
    HDU
    西电OJ
    西电OJ
    西电OJ
    USACO 2.1-Healthy Holsteins
    USACO 2.1-Sorting a Three-Valued Sequence
    HDU
    UVA
    codeforces 811A Vladik and Courtesy
  • 原文地址:https://www.cnblogs.com/wangxiaokun/p/6953986.html
Copyright © 2011-2022 走看看