Chinaunix首页 | 论坛 | 博客
  • 博客访问: 246299
  • 博文数量: 53
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-01 10:17
文章分类

全部博文(53)

文章存档

2013年(53)

分类: C/C++

2013-10-07 19:50:43

原文地址:epoll函数 作者:vangoghiscoding

1)、epoll_create函数
    函数声明:int epoll_create(int size)
   该函数生成一个epoll专用的文件描述符,其中的参数是指定生成描述符的最大范围。

2)、epoll_ctl函数
   函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
   该函数用于控制某个文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:
   epfd:由 epoll_create 生成的epoll专用的文件描述符;
   op:要进行的操作,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修改、   EPOLL_CTL_DEL 删除;
   fd:关联的文件描述符;
   event:指向epoll_event的指针;
   如果调用成功则返回0,不成功则返回-1。

3)、epoll_wait函数
   函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
   该函数用于轮询I/O事件的发生。
   参数:
   epfd:由epoll_create 生成的epoll专用的文件描述符;
   epoll_event:用于回传代处理事件的数组;
   maxevents:每次能处理的事件数;
   timeout:等待I/O事件发生的超时值;
 

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <fcntl.h>
  6. #include <errno.h>

  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <sys/epoll.h>
  10. #include <netdb.h>

  11. #define MAXEVENTS 64

  12. static int
  13. create_and_bind (char *port)
  14. {
  15.     struct addrinfo hints;
  16.     struct addrinfo *result, *rp;
  17.     int s, sfd;

  18.     memset (&hints, 0, sizeof (struct addrinfo));
  19.     hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
  20.     hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
  21.     hints.ai_flags = AI_PASSIVE; /* All interfaces */

  22.     s = getaddrinfo (NULL, port, &hints, &result);
  23.     if (s != 0)
  24.     {
  25.         fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (s));
  26.         return -1;
  27.     }

  28.     for (rp = result; rp != NULL; rp = rp->ai_next)
  29.     {
  30.         sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
  31.         if (sfd == -1)
  32.         continue;

  33.         s = bind (sfd, rp->ai_addr, rp->ai_addrlen);
  34.         if (s == 0)
  35.         {
  36.             /* We managed to bind */
  37.             break;
  38.         }

  39.         close (sfd);
  40.     }

  41.     if (rp == NULL)
  42.     {
  43.         fprintf (stderr, "Could not bind\n");
  44.         return -1;
  45.     }

  46.     freeaddrinfo (result);

  47.     return sfd;
  48. }


  49. static int
  50. make_socket_non_blocking (int sfd)
  51. {
  52.     int flags, s;

  53.     flags = fcntl (sfd, F_GETFL, 0);
  54.     if (flags == -1)
  55.     {
  56.         perror ("fcntl");
  57.         return -1;
  58.     }

  59.     flags |= O_NONBLOCK;
  60.     s = fcntl (sfd, F_SETFL, flags);
  61.     if (s == -1)
  62.     {
  63.         perror ("fcntl");
  64.         return -1;
  65.     }

  66.     return 0;
  67. }


  68. int
  69. main (int argc, char *argv[])
  70. {
  71.     int sfd, s;
  72.     int efd;
  73.     struct epoll_event event;
  74.     struct epoll_event *events;

  75.     if (argc != 2)
  76.     {
  77.         fprintf (stderr, "Usage: %s [port]\n", argv[0]);
  78.         exit (EXIT_FAILURE);
  79.     }

  80.     sfd = create_and_bind (argv[1]);
  81.     if (sfd == -1)
  82.     {
  83.         abort ();
  84.     }

  85.     s = make_socket_non_blocking (sfd);
  86.     if (s == -1)
  87.     {
  88.         abort ();
  89.     }

  90.     s = listen (sfd, SOMAXCONN);
  91.     if (s == -1)
  92.     {
  93.         perror ("listen");
  94.         abort ();
  95.     }

  96.     efd = epoll_create1 (0);
  97.     if (efd == -1)
  98.     {
  99.         perror ("epoll_create");
  100.         abort ();
  101.     }

  102.     event.data.fd = sfd;
  103.     event.events = EPOLLIN | EPOLLET;
  104.     s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);
  105.     if (s == -1)
  106.     {
  107.         perror ("epoll_ctl");
  108.         abort ();
  109.     }

  110.     /* Buffer where events are returned */
  111.     events = calloc (MAXEVENTS, sizeof event);

  112.     /* The event loop */
  113.     while (1)
  114.     {
  115.         int n, i;

  116.         n = epoll_wait (efd, events, MAXEVENTS, -1);
  117.         for (i = 0; i < n; i++)
  118.         {
  119.             if ((events[i].events & EPOLLERR) ||
  120.                 (events[i].events & EPOLLHUP) ||
  121.                 (!(events[i].events & EPOLLIN)))
  122.             {
  123.             /* An error has occured on this fd, or the socket is not
  124.             ready for reading (why were we notified then?) */
  125.                 fprintf (stderr, "epoll error\n");
  126.                 close (events[i].data.fd);
  127.                 continue;
  128.             }
  129.             else if (sfd == events[i].data.fd)
  130.             {
  131.                 /* We have a notification on the listening socket, which
  132.                 means one or more incoming connections. */

  133.                 while (1)
  134.                 {
  135.                     struct sockaddr in_addr;
  136.                     socklen_t in_len;
  137.                     int infd;
  138.                     char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

  139.                     in_len = sizeof in_addr;
  140.                     infd = accept (sfd, &in_addr, &in_len);
  141.                     if (infd == -1)
  142.                     {
  143.                         if ((errno == EAGAIN) ||
  144.                         (errno == EWOULDBLOCK))
  145.                         {
  146.                             /* We have processed all incoming
  147.                             connections. */
  148.                             break;
  149.                         }
  150.                         else
  151.                         {
  152.                             perror ("accept");
  153.                             break;
  154.                         }
  155.                     }

  156.                     s = getnameinfo (&in_addr, in_len,
  157.                             hbuf, sizeof hbuf,
  158.                             sbuf, sizeof sbuf,
  159.                             NI_NUMERICHOST | NI_NUMERICSERV);
  160.                     if (s == 0)
  161.                     {
  162.                             printf("Accepted connection on descriptor %d "
  163.                             "(host=%s, port=%s)\n", infd, hbuf, sbuf);
  164.                     }

  165.                     /* Make the incoming socket non-blocking and add it to the
  166.                     list of fds to monitor. */
  167.                     s = make_socket_non_blocking (infd);
  168.                     if (s == -1)
  169.                         abort ();

  170.                     event.data.fd = infd;
  171.                     event.events = EPOLLIN | EPOLLET;
  172.                     s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);
  173.                     if (s == -1)
  174.                     {
  175.                         perror ("epoll_ctl");
  176.                         abort ();
  177.                     }
  178.                 }

  179.                 continue;
  180.             }
  181.             else
  182.             {
  183.                 /* We have data on the fd waiting to be read. Read and
  184.                 display it. We must read whatever data is available
  185.                 completely, as we are running in edge-triggered mode
  186.                 and won't get a notification again for the same
  187.                 data. */
  188.                 int done = 0;

  189.                 while (1)
  190.                 {
  191.                     ssize_t count;
  192.                     char buf[512];

  193.                     count = read (events[i].data.fd, buf, sizeof buf);
  194.                     if (count == -1)
  195.                     {
  196.                         /* If errno == EAGAIN, that means we have read all
  197.                         data. So go back to the main loop. */
  198.                         if (errno != EAGAIN)
  199.                         {
  200.                             perror ("read");
  201.                             done = 1;
  202.                         }
  203.                         break;
  204.                     }
  205.                     else if (count == 0)
  206.                     {
  207.                         /* End of file. The remote has closed the
  208.                         connection. */
  209.                         done = 1;
  210.                         break;
  211.                     }

  212.                     /* Write the buffer to standard output */
  213.                     s = write (1, buf, count);
  214.                     if (s == -1)
  215.                     {
  216.                         perror ("write");
  217.                         abort ();
  218.                     }
  219.                 }

  220.                 if (done)
  221.                 {
  222.                     printf ("\nClosed connection on descriptor %d\n",
  223.                     events[i].data.fd);

  224.                     /* Closing the descriptor will make epoll remove it
  225.                     from the set of descriptors which are monitored. */
  226.                     close (events[i].data.fd);
  227.                 }
  228.             }
  229.         }
  230.     }

  231.     free (events);

  232.     close (sfd);

  233.     return EXIT_SUCCESS;
  234. }

main() first calls create_and_bind() which sets up the socket. It then makes the socket non-blocking, and then calls listen(2). It then creates an epoll instance in efd, to which it adds the listening socket sfd to watch for input events in an edge-triggered mode.

The outer while loop is the main events loop. It calls epoll_wait(2), where the thread remains blocked waiting for events. When events are available, epoll_wait(2) returns the events in the events argument, which is a bunch of epoll_event structures.

阅读(1716) | 评论(0) | 转发(0) |
0

上一篇:inet_pton函数

下一篇:虚函数的作用

给主人留下些什么吧!~~