Linux IO multiplexing epoll network programming

Linux IO multiplexing epoll network programming

Preface

This chapter uses basic Linux functions and epoll calls to write a complete server and client example that can run on Linux. The functions of the client and server are as follows:

  • The client reads a line from standard input and sends it to the server
  • The server reads a line from the network and outputs it to the client
  • The client receives the response from the server and outputs this line to standard output

Server

The code is as follows:

#include <unistd.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h> /* inet(3) functions */
#include <sys/epoll.h> /* epoll function */
#include <fcntl.h> /* nonblocking */
#include <sys/resource.h> /*setrlimit */
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define MAXEPOLLSIZE 10000
#define MAXLINE 10240
int handle(int connfd);
int setnonblocking(int sockfd)
{
  if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1) {
    return -1;
  }
  return 0;
}
int main(int argc, char **argv)
{
  int servPort = 6888;
  int listenq = 1024;
  int listenfd, connfd, kdpfd, nfds, n, nread, curfds, acceptCount = 0;
  struct sockaddr_in servaddr, cliaddr;
  socklen_t socklen = sizeof(struct sockaddr_in);
  struct epoll_event ev;
  struct epoll_event events[MAXEPOLLSIZE];
  struct rlimit rt;
  char buf[MAXLINE];
  /* Set the maximum number of files each process is allowed to open */
  rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
  if (setrlimit(RLIMIT_NOFILE, &rt) == -1) 
  {
    perror("setrlimit error");
    return -1;
  }
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET; 
  servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
  servaddr.sin_port = htons(servPort);
  listenfd = socket(AF_INET, SOCK_STREAM, 0); 
  if (listenfd == -1) {
    perror("can't create socket file");
    return -1;
  }
  int opt ​​= 1;
  setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  if (setnonblocking(listenfd) < 0) {
    perror("setnonblock error");
  }
  if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1) 
  {
    perror("bind error");
    return -1;
  } 
  if (listen(listenfd, listenq) == -1) 
  {
    perror("listen error");
    return -1;
  }
  /* Create an epoll handle and add the listening socket to the epoll set*/
  kdpfd = epoll_create(MAXEPOLLSIZE);
  ev.events = EPOLLIN | EPOLLET;
  ev.data.fd = listenfd;
  if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) 
  {
    fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
    return -1;
  }
  curfds = 1;
  printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", servPort, MAXEPOLLSIZE, listenq);
  for (;;) {
    /* Wait for an event to occur */
    nfds = epoll_wait(kdpfd, events, curfds, -1);
    if (nfds == -1)
    {
      perror("epoll_wait");
      continue;
    }
    /* Handle all events */
    for (n = 0; n < nfds; ++n)
    {
      if (events[n].data.fd == listenfd) 
      {
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
        if (connfd < 0) 
        {
          perror("accept error");
          continue;
        }
        sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
        printf("%d:%s", ++acceptCount, buf);

        if (curfds >= MAXEPOLLSIZE) {
          fprintf(stderr, "too many connections, more than %d\n", MAXEPOLLSIZE);
          close(connfd);
          continue;
        } 
        if (setnonblocking(connfd) < 0) {
          perror("setnonblocking error");
        }
        ev.events = EPOLLIN | EPOLLET;
        ev.data.fd = connfd;
        if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)
        {
          fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
          return -1;
        }
        curfds++;
        continue;
      } 
      // Process client request if (handle(events[n].data.fd) < 0) {
        epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
        curfds--;
      }
    }
  }
  close(listenfd);
  return 0;
}
int handle(int connfd) {
  int nread;
  char buf[MAXLINE];
  nread = read(connfd, buf, MAXLINE); //Read client socket stream if (nread == 0) {
    printf("client close the connection\n");
    close(connfd);
    return -1;
  } 
  if (nread < 0) {
    perror("read error");
    close(connfd);
    return -1;
  }  
  write(connfd, buf, nread); //respond to the client return 0;
}

Compile

Compile and start the server

gcc epollserver.c -o epollserver
./epollserver

Summarize

The above is the full content of this article. I hope that the content of this article will have certain reference learning value for your study or work. Thank you for your support of 123WORDPRESS.COM. If you want to learn more about this, please check out the following links

You may also be interested in:
  • A detailed introduction to Linux IO
  • Tutorial on using iostat command in Linux
  • Interesting explanation of Linux's Socket IO model
  • A detailed introduction to the five IO models under Linux
  • Analyzing Linux high-performance network IO and Reactor model

<<:  Which loop is the fastest in JavaScript?

>>:  MySQL compression usage scenarios and solutions

Recommend

Nginx rewrite regular matching rewriting method example

Nginx's rewrite function supports regular mat...

Detailed explanation of mysql filtering replication ideas

Table of contents mysql filtered replication Impl...

Implementation of whack-a-mole game in JavaScript

This article shares the specific code for JavaScr...

CSS3 achieves conic-gradient effect

grammar: background-image: conic-gradient(from an...

Steps for encapsulating element-ui pop-up components

Encapsulate el-dialog as a component When we use ...

JavaScript imitates Jingdong magnifying glass special effects

This article shares the specific code of JavaScri...

Detailed explanation of TS object spread operator and rest operator

Table of contents Overview Object rest attribute ...

How to perform query caching in MySQL and how to solve failures

We all know that we need to understand the proper...

VUE implements token login verification

This article example shares the specific code of ...

Textarea tag in HTML

<textarea></textarea> is used to crea...

How to run postgreSQL with docker

1. Install Docker. Reference URL: Docker Getting ...