epoll的helloworld

编程技术  /  houtizong 发布于 3年前   168
转https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
说明:介绍来自http://baike.baidu.com/view/1385104.htm
epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它不会复用文件描述符集合来传递结果而迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的电平触发(Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

官方的运行不了,有错误,看我这个
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>#include <errno.h>#define MAXEVENTS 64static intmake_socket_non_blocking (int sfd){  int flags, s;  flags = fcntl (sfd, F_GETFL, 0);  if (flags == -1)    {      perror ("fcntl");      return -1;    }  flags |= O_NONBLOCK;  s = fcntl (sfd, F_SETFL, flags);  if (s == -1)    {      perror ("fcntl");      return -1;    }  return 0;}static intcreate_and_bind (char *port){  struct addrinfo hints;  struct addrinfo *result, *rp;  int s, sfd;  memset (&hints, 0, sizeof (struct addrinfo));  hints.ai_family = AF_UNSPEC;     /* Return IPv4 and IPv6 choices */  hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */  hints.ai_flags = AI_PASSIVE;     /* All interfaces */  s = getaddrinfo (NULL, port, &hints, &result);  if (s != 0)    {      fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s));      return -1;    }  for (rp = result; rp != NULL; rp = rp->ai_next)    {      sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);      if (sfd == -1)        continue;      s = bind (sfd, rp->ai_addr, rp->ai_addrlen);      if (s == 0)        {          /* We managed to bind successfully! */          break;        }      close (sfd);    }  if (rp == NULL)    {      fprintf (stderr, "Could not bind\n");      return -1;    }  freeaddrinfo (result);  return sfd;}intmain (int argc, char *argv[]){  int sfd, s;  int efd;  struct epoll_event event;  struct epoll_event *events;  if (argc != 2)    {      fprintf (stderr, "Usage: %s [port]\n", argv[0]);      exit (EXIT_FAILURE);    }  sfd = create_and_bind (argv[1]);  if (sfd == -1)    abort ();  s = make_socket_non_blocking (sfd);  if (s == -1)    abort ();  s = listen (sfd, SOMAXCONN);  if (s == -1)    {      perror ("listen");      abort ();    }  efd = epoll_create (0);//error in original page  if (efd == -1)    {      perror ("epoll_create");      abort ();    }  event.data.fd = sfd;  event.events = EPOLLIN | EPOLLET;  s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);  if (s == -1)    {      perror ("epoll_ctl");      abort ();    }  /* Buffer where events are returned */  events = calloc (MAXEVENTS, sizeof event);  /* The event loop */  while (1)    {      int n, i;      n = epoll_wait (efd, events, MAXEVENTS, -1);      for (i = 0; i < n; i++){  if ((events[i].events & EPOLLERR) ||              (events[i].events & EPOLLHUP) ||              (!(events[i].events & EPOLLIN)))    {              /* An error has occured on this fd, or the socket is not                 ready for reading (why were we notified then?) */      fprintf (stderr, "epoll error\n");      close (events[i].data.fd);      continue;    }  else if (sfd == events[i].data.fd)    {              /* We have a notification on the listening socket, which                 means one or more incoming connections. */              while (1)                {                  struct sockaddr in_addr;                  socklen_t in_len;                  int infd;                  char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];                  in_len = sizeof in_addr;                  infd = accept (sfd, &in_addr, &in_len);                  if (infd == -1)                    {                      if ((errno == EAGAIN) ||                          (errno == EWOULDBLOCK))                        {                          /* We have processed all incoming                             connections. */                          break;                        }                      else                        {                          perror ("accept");                          break;                        }                    }                  s = getnameinfo (&in_addr, in_len,                                   hbuf, sizeof hbuf,                                   sbuf, sizeof sbuf,                                   NI_NUMERICHOST | NI_NUMERICSERV);                  if (s == 0)                    {                      printf("Accepted connection on descriptor %d "                             "(host=%s, port=%s)\n", infd, hbuf, sbuf);                    }                  /* Make the incoming socket non-blocking and add it to the                     list of fds to monitor. */                  s = make_socket_non_blocking (infd);                  if (s == -1)                    abort ();                  event.data.fd = infd;                  event.events = EPOLLIN | EPOLLET;                  s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);                  if (s == -1)                    {                      perror ("epoll_ctl");                      abort ();                    }                }              continue;            }          else            {              /* We have data on the fd waiting to be read. Read and                 display it. We must read whatever data is available                 completely, as we are running in edge-triggered mode                 and won't get a notification again for the same                 data. */              int done = 0;              while (1)                {                  ssize_t count;                  char buf[512];                  count = read (events[i].data.fd, buf, sizeof buf);                  if (count == -1)                    {                      /* If errno == EAGAIN, that means we have read all                         data. So go back to the main loop. */                      if (errno != EAGAIN)                        {                          perror ("read");                          done = 1;                        }                      break;                    }                  else if (count == 0)                    {                      /* End of file. The remote has closed the                         connection. */                      done = 1;                      break;                    }                  /* Write the buffer to standard output */                  s = write (1, buf, count);                  if (s == -1)                    {                      perror ("write");                      abort ();                    }                }              if (done)                {                  printf ("Closed connection on descriptor %d\n",                          events[i].data.fd);                  /* Closing the descriptor will make epoll remove it                     from the set of descriptors which are monitored. */                  close (events[i].data.fd);                }            }        }    }  free (events);  close (sfd);  return EXIT_SUCCESS;}

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客