Chinaunix首页 | 论坛 | 博客
  • 博客访问: 288217
  • 博文数量: 95
  • 博客积分: 618
  • 博客等级: 中士
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-28 13:39
文章分类

全部博文(95)

文章存档

2015年(65)

2013年(1)

2012年(10)

2011年(19)

分类: C/C++

2015-06-24 12:15:49


点击(此处)折叠或打开

  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. using namespace std;
  11. #define MAXLINE 5
  12. #define OPEN_MAX 100
  13. #define LISTENQ 20
  14. #define SERV_PORT 5000
  15. #define INFTIM 1000
  16. void setnonblocking(int sock)//将套接字设置为非阻塞
  17. {
  18.     int opts;
  19.     opts=fcntl(sock,F_GETFL);
  20.     if(opts<0)
  21.     {
  22.         perror("fcntl(sock,GETFL)");
  23.         exit(1);
  24.     }
  25.     opts = opts|O_NONBLOCK;
  26.     if(fcntl(sock,F_SETFL,opts)<0)
  27.     {
  28.         perror("fcntl(sock,SETFL,opts)");
  29.         exit(1);
  30.     }
  31. }
  32. int main(int argc, char* argv[])
  33. {
  34.     int i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;
  35.     ssize_t n;
  36.     char line[MAXLINE];
  37.     socklen_t clilen;
  38.     if ( 2 == argc )
  39.     {
  40.         if( (portnumber = atoi(argv[1])) < 0 )
  41.         {
  42.             fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
  43.             return 1;
  44.         }
  45.     }
  46.     else
  47.     {
  48.         fprintf(stderr,"Usage:%s portnumber/a/n",argv[0]);
  49.         return 1;
  50.     }
  51.     struct epoll_event ev,events[20]; //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
  52.     epfd=epoll_create(256); //生成用于处理accept的epoll专用的文件描述符
  53.     struct sockaddr_in clientaddr;
  54.     struct sockaddr_in serveraddr;
  55.     listenfd = socket(AF_INET, SOCK_STREAM, 0);
  56.     setnonblocking(listenfd); //把socket设置为非阻塞方式
  57.     ev.data.fd=listenfd; //设置与要处理的事件相关的文件描述符
  58.     ev.events=EPOLLIN|EPOLLET; //设置要处理的事件类型

  59.     epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); //注册epoll事件
  60.     bzero(&serveraddr, sizeof(serveraddr));
  61.     serveraddr.sin_family = AF_INET;
  62.     char *local_addr="127.0.0.1";
  63.     inet_aton(local_addr,&(serveraddr.sin_addr));
  64.     serveraddr.sin_port=htons(portnumber);
  65.     bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
  66.     listen(listenfd, LISTENQ);
  67.     maxi = 0;
  68.     for ( ; ; ) {
  69.          nfds=epoll_wait(epfd,events,20,500); //等待epoll事件的发生
  70.         for(i=0;i<nfds;++i) //处理所发生的所有事件
  71.         {
  72.             if(events[i].data.fd==listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
  73.             {
  74.                 connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
  75.                 if(connfd<0){
  76.                     perror("connfd<0");
  77.                     exit(1);
  78.                 }
  79.                 char *str = inet_ntoa(clientaddr.sin_addr);
  80.                 cout << "accapt a connection from " << str << endl;
  81.                 ev.data.fd=connfd; //设置用于读操作的文件描述符
  82.                 ev.events=EPOLLIN|EPOLLET; //设置用于注测的读操作事件
  83.                 epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //注册ev
  84.             }
  85.             else if(events[i].events&EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。
  86.             {
  87.                 cout << "EPOLLIN" << endl;
  88.                 if ( (sockfd = events[i].data.fd) < 0)
  89.                     continue;
  90.                 if ( (n = read(sockfd, line, MAXLINE)) < 0) {
  91.                     if (errno == ECONNRESET) {
  92.                         close(sockfd);
  93.                         events[i].data.fd = -1;
  94.                     } else
  95.                         std::cout<<"readline error"<<std::endl;
  96.                 } else if (n == 0) {
  97.                     close(sockfd);
  98.                     events[i].data.fd = -1;
  99.                 }
  100.                 line[n] = '/0';
  101.                 cout << "read " << line << endl;
  102.                 ev.data.fd=sockfd; //设置用于写操作的文件描述符
  103.                 ev.events=EPOLLOUT|EPOLLET; //设置用于注测的写操作事件
  104.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改sockfd上要处理的事件为EPOLLOUT
  105.             }
  106.             else if(events[i].events&EPOLLOUT) // 如果有数据发送
  107.             {
  108.                 sockfd = events[i].data.fd;
  109.                 write(sockfd, line, n);
  110.                 ev.data.fd=sockfd; //设置用于读操作的文件描述符
  111.                 ev.events=EPOLLIN|EPOLLET; //设置用于注测的读操作事件
  112.                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改sockfd上要处理的事件为EPOLIN
  113.             }
  114.         }
  115.     }
  116.     return 0;
  117. }

阅读(541) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~