C   66

p2.c

Guest on 5th May 2022 11:02:30 PM

  1. #define _GNU_SOURCE
  2.  
  3. #include <arpa/inet.h>
  4. #include <netinet/in.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/epoll.h>
  8. #include <sys/socket.h>
  9. #include <unistd.h>
  10. #include "common.h"
  11.  
  12. struct fdinfo {
  13.         enum {
  14.                 LSOCK,
  15.                 CLIENT
  16.         } type;
  17.         int fd;
  18.         struct sockaddr_in sin;
  19. };
  20.  
  21. static void print_event(int fd, struct epoll_event ev) {
  22.         char flags_str[200];
  23.  
  24.         flags_str[0] = 0;
  25.         flags_str[1] = 0; /* dirty */
  26.  
  27.         if (ev.events & EPOLLIN )       strcat(flags_str, "|EPOLLIN");
  28.         if (ev.events & EPOLLOUT)       strcat(flags_str, "|EPOLLOUT");
  29.         if (ev.events & EPOLLERR)       strcat(flags_str, "|EPOLLERR");
  30.         if (ev.events & EPOLLHUP)       strcat(flags_str, "|EPOLLHUP");
  31.         if (ev.events & EPOLLRDHUP)     strcat(flags_str, "|EPOLLRDHUP");
  32.         if (ev.events & EPOLLPRI)       strcat(flags_str, "|EPOLLPRI");
  33.         if (ev.events & EPOLLET)        strcat(flags_str, "|EPOLLET");
  34.         if (ev.events & EPOLLONESHOT)   strcat(flags_str, "|EPOLLONESHOT");
  35.  
  36.         fprintf(stderr, "Event for fd %i. Flags=(%s).\n",
  37.                         fd, flags_str+1);
  38. }
  39.  
  40. int start_listener(int port);
  41. void service(int epfd);
  42.  
  43. int main () {
  44.         int epfd = epoll_create(1);
  45.         int lsock = start_listener(9000);
  46.         struct epoll_event ev;
  47.         struct fdinfo *fdinfo;
  48.         int ret;
  49.  
  50.         fdinfo = malloc(sizeof (struct fdinfo));
  51.         fdinfo->type = LSOCK;
  52.         fdinfo->fd = lsock;
  53.  
  54.         ev.data.ptr = fdinfo;
  55.         ev.events = EPOLLIN;
  56.  
  57.         ret = epoll_ctl(epfd, EPOLL_CTL_ADD, lsock, &ev);
  58.         if (ret < 0)
  59.                 die("epoll_ctl.1");
  60.  
  61.         service(epfd);
  62.  
  63.         close(epfd);
  64.  
  65.         return 0;
  66. }
  67.  
  68. int start_listener(int port) {
  69.         struct sockaddr_in listen_addr;
  70.         int lsock;
  71.         int ret;
  72.  
  73.         lsock = socket(AF_INET, SOCK_STREAM, 0);
  74.         if (lsock < 0)
  75.                 die("socket");
  76.  
  77.         memset(&listen_addr, 0, sizeof listen_addr);
  78.         listen_addr.sin_family = AF_INET;
  79.         listen_addr.sin_port = htons(port);
  80.         listen_addr.sin_addr.s_addr = INADDR_ANY;
  81.  
  82.         ret = bind(lsock, (sad*)&listen_addr, sizeof listen_addr);
  83.         if (ret < 0)
  84.                 die("bind");
  85.  
  86.         ret = listen(lsock, 10);
  87.         if (ret < 0)
  88.                 die("listen");
  89.  
  90.         return lsock;
  91. }
  92.  
  93. void accept_one(int epfd, int lsock) {
  94.         int cli;
  95.         struct fdinfo *fdinfo;
  96.         struct epoll_event ev;
  97.         socklen_t crap = sizeof fdinfo->sin;
  98.         int ret;
  99.  
  100.         fdinfo = malloc(sizeof *fdinfo);
  101.  
  102.         cli = accept4(lsock, (sad*)&fdinfo->sin, &crap, SOCK_NONBLOCK);
  103.         if (cli < 0)
  104.                 die("accept");
  105.  
  106.         fdinfo->fd = cli;
  107.         fdinfo->type = CLIENT;
  108.  
  109.         ev.data.ptr = fdinfo;
  110.         ev.events = EPOLLIN | EPOLLRDHUP;
  111.  
  112.         ret = epoll_ctl(epfd, EPOLL_CTL_ADD, cli, &ev);
  113.         if (ret < 0)
  114.                 die("epoll_ctl.2");
  115. }
  116.  
  117. void handle_cli(struct fdinfo *fdinfo) {
  118.         int fd = fdinfo->fd;
  119.         int t;
  120.         char buf1[101], buf2[101];
  121.  
  122.         inet_ntop(AF_INET, &fdinfo->sin.sin_addr, buf1, sizeof fdinfo->sin);
  123.  
  124.         buf2[0] = 0;
  125.         t = read(fd, buf2, 100);
  126.         if (t > 0) {
  127.                 buf2[t] = 0;
  128.                 printf("%s mandĆ³ %s\n"n", buf1, buf2);
  129.         }
  130.         write(fd, buf2, t);
  131. }
  132.  
  133. void kill_cli(int epfd, struct fdinfo *fdinfo) {
  134.         char buf[100];
  135.         int fd = fdinfo->fd;
  136.         free(fdinfo);
  137.  
  138.         inet_ntop(AF_INET, &fdinfo->sin.sin_addr, buf, sizeof fdinfo->sin);
  139.  
  140.         printf("Chau %s!\n", buf);
  141.  
  142.         epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
  143.         close(fd);
  144. }
  145.  
  146. void handle_event(int epfd, struct epoll_event ev) {
  147.         struct fdinfo *fdinfo = ev.data.ptr;
  148.  
  149.         switch (fdinfo->type) {
  150.         case LSOCK:
  151.                 accept_one(epfd, fdinfo->fd);
  152.                 break;
  153.         case CLIENT:
  154.                 print_event(fdinfo->fd, ev);
  155.  
  156.                 if (ev.events & EPOLLIN && !(ev.events & EPOLLRDHUP))
  157.                         handle_cli(fdinfo);
  158.                 else if (ev.events & EPOLLRDHUP)
  159.                         kill_cli(epfd, fdinfo);
  160.  
  161.                 break;
  162.         }
  163. }
  164.  
  165. void service(int epfd) {
  166.         int i, n;
  167.         struct epoll_event evs[10];
  168.  
  169.         for (;;) {
  170.                 n = epoll_wait(epfd, evs, 10, 5000);
  171.  
  172.                 if (n < 0)
  173.                         die("epoll_wait");
  174.  
  175.                 if (n == 0) {
  176.                         printf("Que aburrimiento che....\n");
  177.                         continue;
  178.                 }
  179.  
  180.                 for (i=0; i<n; i++)
  181.                         handle_event(epfd, evs[i]);
  182.         }

Raw Paste


Login or Register to edit or fork this paste. It's free.