linux epoll,poll,select

epoll function usage, and a little poll and select

1, LT epoll is an improved version of the poll and select functions.

Feature is that after reading the buffer, the buffer if there is content, then, epoll_wait function will return until the buffer is read them all.

2, ET's epoll (blocking)

Feature is that after reading the buffer, the buffer is there regardless of content, epoll_wait function will not return until the end once again send a message to come. Estimated that some readers will think of a while to read, but there is a fatal problem, because file descriptors are blocked, so when all the reading, where the process will function in blocking recv, and then not be able to deal with other connected.

3, ET of the epoll (non-blocking), the most efficient method.

Feature is that after reading the buffer, the buffer is there regardless of content, epoll_wait function will not return until the end once again send a message to come. But you can advance with the fcntl file descriptor is set to a non-blocking manner, so that after a while has been read, when read them all, recv function will not be blocked.

ET is the epoll (non-blocking) Examples:

#include <stdio.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

int main(int argc, char** argv){

  int port = atoi(argv[1]);
  int lfd = socket(AF_INET, SOCK_STREAM, 0);

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = INADDR_ANY;

  bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
  listen(lfd, 5);

  int efd = epoll_create(10);

  struct epoll_event re;
  re.events = EPOLLIN;
  re.data.fd = lfd;

  epoll_ctl(efd, EPOLL_CTL_ADD, lfd, &re);

  struct epoll_event events[100];
  
  while(1){
    int ret = epoll_wait(efd, events, 100, -1);
    printf("======================wait=======\n");
    if(ret == -1){
      perror("epoll_wait");
      exit(1);
    }

    for(int i = 0; i < ret; ++i){
      if(events[i].data.fd == lfd){
        int cfd = accept(lfd, NULL, NULL);

        int flags = fcntl(cfd, F_GETFL);
        flags |= O_NONBLOCK;
        fcntl(cfd, F_SETFL, flags);
    
        struct epoll_event re;
        re.events = EPOLLIN | EPOLLET;
        re.data.fd = cfd;
        epoll_ctl(efd, EPOLL_CTL_ADD, cfd, &re);
        break;
      }
      char buf[3];

      int ret;
      while((ret = recv(events[i].data.fd, buf, sizeof buf, 0)) > 0){
        write(STDOUT_FILENO, buf, ret);
      }
      
      if(ret == 0){
        epoll_ctl(efd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
        close(events[i].data.fd);
        printf("client disconnet\n");
      }
      else if(ret == -1 && errno == EAGAIN){
        printf("read over\n");  
      }
    }
  }
}

poll function examples:

#include <stdio.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char** argv){

  int port = atoi(argv[1]);
  int lfd = socket(AF_INET, SOCK_STREAM, 0);

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = INADDR_ANY;

  bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
  listen(lfd, 5);

  struct pollfd pfd[1024];
  for(int i = 0; i < 1024; ++i){
    pfd[i].fd = -1;
  }
  pfd[0].fd = lfd;
  pfd[0].events = POLLIN;
  nfds_t maxfd = 0;
  
  while(1){
    int ret = poll(pfd, maxfd + 1, -1);
    printf("--------------poll------\n");
    if(pfd[0].revents & POLLIN){
      int cfd = accept(lfd, NULL, NULL);
      for(int i = 0; i < 1024; ++i){
        if(pfd[i].fd == -1){
          pfd[i].fd = cfd;
          pfd[i].events = POLLIN;
          maxfd++;
          break;
        }
      }
      continue;
    }

    for(int i = 0; i <= maxfd; ++i){
      if(pfd[i].revents & POLLIN){
        char buf[64];
        int ret = recv(pfd[i].fd, buf, sizeof buf, 0);
        if(ret == 0){
          pfd[i].fd = -1;
          close(pfd[i].fd);
          printf("client is disconnet\n");
        }
        else{
          write(STDOUT_FILENO, buf, ret);
        }
      }
    } 
    
  }
}

Examples can be seen by comparison of the poll and epoll:

  • epoll do not need to decide in advance the size of the array. poll needs.
  • epoll internal efficiency is achieved with a red-black tree, not connected with the increase, significantly becomes low. poll list is implemented, so the performance decreases with the increase of connection. poll can not be used in windows. epoll is cross-platform.
  • Under way, the size of the array is an array of select died implemented by the kernel code is written, that is 1024, I would like to increase only recompile the kernel. But select is cross-platform.

c / c ++ mutual learning QQ group: 877 684 253

I micro letter: xiaoshitou5854

Guess you like

Origin www.cnblogs.com/xiaoshiwang/p/11110204.html