几种并发服务器模型的实现:多线程,多进程,select,poll,epoll - rail

几种并发服务器模型的实现:多线程,多进程,select,poll,epoll - rail

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "rio.h"
#include <signal.h>
#include <pthread.h>

#define ERR_EXIT(m) \
  do { \
    perror(m);\
    exit(EXIT_FAILURE);\
  }while(0)

static void do_service(int fd)
{
  rio_t rt;
  rio_init(&rt, fd);
  char recvbuf[1024] = {0};
  int ret;
  int rcnt = 0;
  while(1)
  {
    memset(recvbuf, 0, sizeof recvbuf);
    ret = rio_readline(&rt, recvbuf, 1024);
     if(ret == 0)
     {
     close(fd);
     break;
     }
     write(fd, recvbuf, strlen(recvbuf)) ;
  }
}

void handle(int signum)
{
  printf("hello\n");
}

void *pthread_func(void *arg)
{
  pthread_detach(pthread_self());
  int *q = (int*)arg;
   int p = *(int*)arg;
   free(q);
   do_service(p);
   close(p);
}
int listenf();

int main(int argc, const char *argv[])
{
  if(signal(SIGPIPE, handle) == SIG_ERR)
    ERR_EXIT("signal");
  int listenfd = listenf();

  struct sockaddr_in cliaddr;
  bzero(&cliaddr, sizeof(cliaddr));
  socklen_t cli_len = sizeof cliaddr;
  int clientfd;
  while(1)
  {
  clientfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cli_len);
  if(clientfd == -1)  
  {
    close(listenfd);
    ERR_EXIT("accept");
  }

  pthread_t tid;
  int *p = (int*)malloc(sizeof(int));
   *p = clientfd;
  pthread_create(&tid, NULL, pthread_func, p);
  }
  close(listenfd);
  return 0;
}

int listenf()
{
  int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
  if(listenfd == -1 )
    ERR_EXIT("listen");

  int on = 1;
  if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
  {
    close(listenfd);
    ERR_EXIT("setsockopt");
  }

  struct sockaddr_in seraddr;
  seraddr.sin_family = AF_INET;
  seraddr.sin_port = htons(8888);
  seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  socklen_t len = sizeof(seraddr);
  if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
  {
    close(listenfd);
    ERR_EXIT("bind");
  }

  if(listen(listenfd, 6) == -1)
  {
    close(listenfd);
    ERR_EXIT("listen");
  }
return listenfd;
}

客户端使用select模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <errno.h>
  5 #include <sys/types.h>
  6 #include <sys/socket.h>
  7 #include <netinet/in.h>
  8 #include <arpa/inet.h>
  9 #include <sys/select.h>
 10 #include <signal.h>
 11 
 12 #define ERR_EXIT(m) \
 13     do { \
 14         perror(m);\
 15         exit(EXIT_FAILURE);\
 16     }while(0)
 17 
 18 static void do_client(int fd)
 19 {
 20     char recvbuf[MAXLINE + 1] = {0};
 21     char sendbuf[MAXLINE + 1] = {0};
 22 
 23     fd_set reade, ready;
 24     FD_ZERO(&reade);
 25     int fd_stdin = fileno(stdin);
 26     FD_SET(fd_stdin, &reade);
 27     FD_SET(fd, &reade);
 28     int fd_max = (fd_stdin > fd) ? fd_stdin : fd;
 29 
 30     int ret;
 31     while(1)
 32     {
 33         ready = reade;
 34         ret = select( fd_max+1, &ready, NULL, NULL, NULL);//轮询
 35         if(ret == -1)
 36         {
 37             if(errno == EINTR)
 38                 continue;
 39             ERR_EXIT("select");
 40         }else if(ret ==  0)
 41         {
 42             continue;
 43         }
 44 
 45         if(FD_ISSET(fd_stdin, &ready))
 46         {
 47             if(fgets(sendbuf, sizeof(sendbuf), stdin) == NULL)
 48             {
 49                 close(fd);
 50                break;
 51             }else
 52             {
 53                 if( -1 == write(fd, sendbuf, strlen(sendbuf)))
 54                     printf("write\n");
 55             }
 56         }
 57 
 58 
 59         if(FD_ISSET(fd, &ready))
 60         {
 61             int nread = read(fd, recvbuf, MAXLINE);
 62             if(nread < 0)
 63                 ERR_EXIT("read");
 64             if(nread == 0)//如果没接收到消息,打印关闭描述符,退出循环
 65             {
 66                 fprintf(stdout, "fd close\n");
 67                 break;
 68             }
 69             fprintf(stdout, "receive:%s", recvbuf);
 70         }
 71         memset(recvbuf, 0, sizeof recvbuf);
 72         memset(sendbuf, 0, sizeof sendbuf);
 73     }
 74 }
 75 void handle(int signum)
 76 {
 77 printf("sigpipe\n");
 78 }
 79 
 80 int main(int argc, const char *argv[])
 81 {
 82     signal(SIGPIPE, SIG_IGN);
 83     int fd = socket(AF_INET, SOCK_STREAM, 0);
 84     if(fd < 0)
 85         ERR_EXIT("socket");
 86 
 87     struct sockaddr_in cliaddr;
 88     cliaddr.sin_family = AF_INET;
 89     cliaddr.sin_port = htons(8888);
 90     cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 91     socklen_t len = sizeof cliaddr;
 92 
 93     int ret ;
 94     if((ret = connect(fd, (struct sockaddr*)&cliaddr, len)) == -1)
 95     {
 96         close(fd);
 97         ERR_EXIT("connect");
 98     }
 99     do_client(fd);
100     close(fd);
101     return 0;
102 }

1.并发多线程服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "rio.h"//封装了网络编程中的readn  writen   readline 3个函数
#include <signal.h>

#define ERR_EXIT(m) \
  do { \
    perror(m);\
    exit(EXIT_FAILURE);\
  }while(0)

static void do_service(int fd)
{
  rio_t rt;
  rio_init(&rt, fd);
  char recvbuf[1024] = {0};
  int ret;
  while(1)
  {
    memset(recvbuf, 0, sizeof recvbuf);
    ret = rio_readline(&rt, recvbuf, 1024);
    if(ret == 0)   
    {
      close(fd);
      exit(EXIT_SUCCESS);
    }
    rio_writen(fd, recvbuf, strlen(recvbuf)) ;
  }
}

void handle(int signum)//对SIGCHLD信号的处理函数
{
  while(waitpid(-1, NULL, WNOHANG) > 0);
  return ;
}

int listenf();//封装了socket,bind,listen3个函数,返回需要监听的连接socket描述符

int main(int argc, const char *argv[])
{
  if(signal(SIGPIPE, SIG_IGN) == SIG_ERR)//对客户端关闭导致的信号的处理
    ERR_EXIT("signal_pipe");
  if(signal(SIGCHLD, handle) == SIG_ERR)//对子进程结束后资源的回收
    ERR_EXIT("signal_chld");


  int listenfd = listenf();

  struct sockaddr_in cliaddr;
  bzero(&cliaddr, sizeof(cliaddr));
  socklen_t cli_len = sizeof cliaddr;
  int clientfd;
  while(1)
  {
    clientfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cli_len);
    if(clientfd == -1)  
    {
      close(listenfd);
      ERR_EXIT("accept");
    }
    
    int pid;
    if((pid = fork()) == -1)
    {
      ERR_EXIT("fork");
    }else if(pid == 0)
    {
      close(listenfd);
      do_service(clientfd);
      exit(EXIT_SUCCESS);
    }
    close(clientfd);
  }
  close(listenfd);
  return 0;
}

int listenf()
{
  int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
  if(listenfd == -1 )
    ERR_EXIT("socket");

  int on = 1;
  if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
  {
    close(listenfd);
    ERR_EXIT("setsockopt");
  }

  struct sockaddr_in seraddr;
  seraddr.sin_family = AF_INET;
  seraddr.sin_port = htons(8888);
  seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  socklen_t len = sizeof(seraddr);
  if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
  {
    close(listenfd);
    ERR_EXIT("bind");
  }

  if(listen(listenfd, 6) == -1)
  {
    close(listenfd);
    ERR_EXIT("listen");
  }
  return listenfd;
}

2.多线程服务器模型:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "rio.h"
#include <signal.h>
#include <pthread.h>

#define ERR_EXIT(m) \
  do { \
    perror(m);\
    exit(EXIT_FAILURE);\
  }while(0)

static void do_service(int fd)
{
  rio_t rt;
  rio_init(&rt, fd);
  char recvbuf[1024] = {0};
  int ret;
  int rcnt = 0;
  while(1)
  {
    memset(recvbuf, 0, sizeof recvbuf);
    ret = rio_readline(&rt, recvbuf, 1024);
     if(ret == 0)
     {
     close(fd);
//		 break;
      pthread_exit(NULL);
     }
     write(fd, recvbuf, strlen(recvbuf)) ;
  }
}

void handle(int signum)
{
  printf("hello\n");
}

void *pthread_func(void *arg)
{
  pthread_detach(pthread_self());
  int *q = (int*)arg;
   int p = *(int*)arg;
   free(q);
   do_service(p);
   close(p);
}
int listenf();

int main(int argc, const char *argv[])
{
  if(signal(SIGPIPE, handle) == SIG_ERR)
    ERR_EXIT("signal");
  int listenfd = listenf();

  struct sockaddr_in cliaddr;
  bzero(&cliaddr, sizeof(cliaddr));
  socklen_t cli_len = sizeof cliaddr;
  int clientfd;
  while(1)
  {
  clientfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cli_len);
  if(clientfd == -1)  
  {
    close(listenfd);
    ERR_EXIT("accept");
  }

  pthread_t tid;
  int *p = (int*)malloc(sizeof(int));
   *p = clientfd;
  pthread_create(&tid, NULL, pthread_func, p);
  }
  close(listenfd);
  return 0;
}

int listenf()
{
  int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
  if(listenfd == -1 )
    ERR_EXIT("listen");

  int on = 1;
  if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
  {
    close(listenfd);
    ERR_EXIT("setsockopt");
  }

  struct sockaddr_in seraddr;
  seraddr.sin_family = AF_INET;
  seraddr.sin_port = htons(8888);
  seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  socklen_t len = sizeof(seraddr);
  if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
  {
    close(listenfd);
    ERR_EXIT("bind");
  }

  if(listen(listenfd, 6) == -1)
  {
    close(listenfd);
    ERR_EXIT("listen");
  }
return listenfd;
}

3.select服务器模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <sys/select.h>
 12 #define MAXLEN 1024
 13 
 14 #define ERR_EXIT(m) \
 15     do { \
 16         perror(m);\
 17         exit(EXIT_FAILURE);\
 18     }while(0)
 19 
 20 int listenf();//封装了网络socket的socekt,bind,listen函数,返回监听的socket描述符
 21 void handle(int signum)//SIGPIPE(子进程结束)的信号的处理
 22 {
 23     printf("hello\n");
 24 }
 25 static void do_select(int);
 26 
 27 int main(int argc, const char *argv[])
 28 {
 29     if(signal(SIGPIPE, handle) == SIG_ERR)
 30         ERR_EXIT("signal");
 31     int listenfd = listenf();
 32     do_select(listenfd);
 33     close(listenfd);
 34     return 0;
 35 }
 36 
 37 int listenf()
 38 {
 39     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 40     if(listenfd == -1 )
 41         ERR_EXIT("listen");
 42 
 43     int on = 1;
 44     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 45     {
 46         close(listenfd);
 47         ERR_EXIT("setsockopt");
 48     }
 49 
 50     struct sockaddr_in seraddr;
 51     seraddr.sin_family = AF_INET;
 52     seraddr.sin_port = htons(8888);
 53     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 54     socklen_t len = sizeof(seraddr);
 55     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 56     {
 57         close(listenfd);
 58         ERR_EXIT("bind");
 59     }
 60 
 61     if(listen(listenfd, 6) == -1)
 62     {
 63         close(listenfd);
 64         ERR_EXIT("listen");
 65     }
 66     return listenfd;
 67 }
 68 
 69 void do_select(int fd)
 70 {
 71     //struct sockaddr_in cliaddr;
 72     //memset(&cliaddr, 0, sizeof(cliaddr));//此处不需要客户端的地址信息
 73     fd_set set;
 74     fd_set rset;
 75     FD_ZERO(&rset);
 76     FD_SET(fd, &rset);
 77     int nready;
 78     int fd_set[MAXLEN];
 79 
 80     int i;
 81     for(i = 0;i < MAXLEN; ++i)
 82         fd_set[i] = -1;
 83     fd_set[0] = fd;
 84 
 85     int maxi = fd;//初始最大轮询fd是监听的fd
 86     int  arrlen = 1;//表示数组长度
 87    
 88    char recvbuf[1024] = {0};
 89     while(1)
 90     {
 91         set = rset;
 92         nready = select(maxi+1, &set, NULL, NULL, NULL);
 93         if(nready == -1)
 94         {
 95             ERR_EXIT("select");
 96         }
 97         if(FD_ISSET(fd, &set))//查看书否有新的客户端请求
 98         {
 99             int clifd = accept(fd, NULL, NULL);
100             if(clifd == -1)
101                 ERR_EXIT("accept");
102             for(i = 1; i < MAXLEN; ++i)
103             { if(fd_set[i] == -1)
104                 {
105                     fd_set[i] = clifd;
106                     break;
107                 }
108             }
109             FD_SET(clifd, &rset);
110             if(clifd > maxi)
111                 maxi = clifd;
112             arrlen++;
113             --nready;
114         }
115 
116         for(i = 1; i < arrlen; ++i)//轮询数据连接
117         {
118             int set_fd = fd_set[i];
119          if(FD_ISSET(set_fd, &set))
120          {
121             int n = read(set_fd, recvbuf, 1024);
122             if(n == -1)
123                 ERR_EXIT("read");
124             else if(n == 0)//客户端退出,
125             {
126               FD_CLR(set_fd, &rset);
127               close(set_fd);
128               fd_set[i] = -1;
129               arrlen--;
130             }
131             write(set_fd, recvbuf, strlen(recvbuf));
132                memset(recvbuf, 0, 1024);
133          if(--nready < 0)
134              break;
135          }
136         }
137     }
138 }
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <poll.h>
 12 #define MAXLEN 1024
 13 
 14 #define ERR_EXIT(m) \
 15     do { \
 16         perror(m);\
 17         exit(EXIT_FAILURE);\
 18     }while(0)
 19 
 20 static void do_service(int);
 21 int listenf();
 22 void handle(int signum)
 23 {
 24     printf("hello\n");
 25 }
 26 static void do_poll(int);
 27 
 28 int main(int argc, const char *argv[])
 29 {
 30     if(signal(SIGPIPE, handle) == SIG_ERR)
 31         ERR_EXIT("signal");
 32     int listenfd = listenf();
 33     do_poll(listenfd);
 34     close(listenfd);
 35     return 0;
 36 }
 37 
 38 int listenf()
 39 {
 40     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 41     if(listenfd == -1 )
 42         ERR_EXIT("listen");
 43 
 44     int on = 1;
 45     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 46     {
 47         close(listenfd);
 48         ERR_EXIT("setsockopt");
 49     }
 50 
 51     struct sockaddr_in seraddr;
 52     seraddr.sin_family = AF_INET;
 53     seraddr.sin_port = htons(8888);
 54     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 55     socklen_t len = sizeof(seraddr);
 56     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 57     {
 58         close(listenfd);
 59         ERR_EXIT("bind");
 60     }
 61 
 62     if(listen(listenfd, 6) == -1)
 63     {
 64         close(listenfd);
 65         ERR_EXIT("listen");
 66     }
 67     return listenfd;
 68 }
 69 
 70 void do_poll(int fd)
 71 {
 72     struct pollfd pfd[MAXLEN];//设置的最大连接数,存放结构体信息
 73     char recvbuf[1024] = {0};
 74     int i;
 75     for(i = 0; i < MAXLEN; ++i)
 76         pfd[i].fd = -1;
 77 
 78     pfd[0].fd = fd;
 79     pfd[0].events = POLLIN;//将监听连接的描述符防止数组开头
 80 
 81     int nready;
 82     int maxi = 0;
 83     while(1)
 84     {
 85         nready = poll(pfd, maxi+1, -1);//轮询的是有效数组长度,不能少1
 86         if(nready == -1)
 87         {
 88             ERR_EXIT("select");
 89         }
 90 
 91         if(pfd[0].revents & POLLIN)//有客户端请求连接
 92         {
 93             int clifd = accept(fd, NULL, NULL);
 94             if(clifd == -1)
 95                 ERR_EXIT("accept");
 96             for(i = 1; i < MAXLEN; ++i)
 97             { 
 98                 if(pfd[i].fd == -1)
 99                 {
100                     pfd[i].fd = clifd;
101                     pfd[i].events = POLLIN;
102                     break;
103                 }
104             }
105             if(i > maxi)
106                 maxi = i;  
107             --nready;
108         }
109 
110         for(i = 1; i <= maxi; ++i)
111         {
112             if(pfd[i].fd == -1)
113                 continue;
114 
115             if( pfd[i].revents & POLLIN)
116             {
117                 int n = read(pfd[i].fd, recvbuf, 1024);
118                 if(n == -1)
119                     ERR_EXIT("read");
120                 else if(n == 0)//客户端退出,则从集合中清除
121                 {
122                     printf("%d close\n", pfd[i].fd);
123                     close(pfd[i].fd); 
124                     pfd[i].fd = -1;
125                     continue;
126                 }
127                 write(pfd[i].fd, recvbuf, strlen(recvbuf));
128                 memset(recvbuf, 0, 1024);
129 
130                 if(--nready < 0)
131                     break;
132             }
133         }
134     }
135 }

5.epoll服务器模型:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <sys/types.h>
  7 #include <sys/stat.h>
  8 #include <sys/socket.h>
  9 #include <arpa/inet.h>
 10 #include <signal.h>
 11 #include <sys/epoll.h>
 12 #define MAXLEN 1024
 13 
 14 #define ERR_EXIT(m) \
 15     do { \
 16         perror(m);\
 17         exit(EXIT_FAILURE);\
 18     }while(0)
 19 
 20 int listenf();
 21 static void do_epoll(int);
 22 
 23 int main(int argc, const char *argv[])
 24 {
 25     int listenfd = listenf();
 26     do_epoll(listenfd);
 27     close(listenfd);
 28     return 0;
 29 }
 30 
 31 int listenf()
 32 {
 33     int listenfd = socket(AF_INET, SOCK_STREAM, 0);//准备一个socketfd
 34     if(listenfd == -1 )
 35         ERR_EXIT("listen");
 36 
 37     int on = 1;
 38     if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)//setsockopt设置端口复用
 39     {
 40         close(listenfd);
 41         ERR_EXIT("setsockopt");
 42     }
 43 
 44     struct sockaddr_in seraddr;
 45     seraddr.sin_family = AF_INET;
 46     seraddr.sin_port = htons(8888);
 47     seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
 48     socklen_t len = sizeof(seraddr);
 49     if(bind(listenfd, (struct sockaddr*)&seraddr, len) == -1)//监听socket端口,
 50     {
 51         close(listenfd);
 52         ERR_EXIT("bind");
 53     }
 54 
 55     if(listen(listenfd, 6) == -1)
 56     {
 57         close(listenfd);
 58         ERR_EXIT("listen");
 59     }
 60     return listenfd;
 61 }
 62 
 63 void do_epoll(int fd)
 64 {
 65     char recvbuf[MAXLEN] = {0};
 66     int epollfd = epoll_create(2048);//设置的最大连接数
 67     if(epollfd == -1)
 68         ERR_EXIT("epoll_create");
 69 
 70     struct epoll_event ev;
 71     ev.data.fd = fd;
 72     ev.events = EPOLLIN;
 73     if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)//加入轮询
 74                  ERR_EXIT("epoll_ctl_add");
 75 
 76     struct epoll_event events[2048];//数组在epoll_wait返回结果的时候使用
 77     int ret;
 78     int i;//在下面while的for循环中遍历使用
 79     int rfd;
 80     int clientfd;
 81     int nread;
 82     while(1)
 83     {
 84         ret = epoll_wait(epollfd, events, 2048, -1);
 85         if(ret == -1)
 86             ERR_EXIT("epoll_wait");
 87 
 88         for(i = 0; i < ret; ++i )
 89         {
 90             rfd = events[i].data.fd;
 91             if(rfd == fd)
 92             {
 93                 if((clientfd = accept(fd, NULL, NULL)) == -1)
 94                 ERR_EXIT("accept");
 95                 ev.data.fd = clientfd;
 96                 ev.events = EPOLLIN;
 97                 if(epoll_ctl(epollfd, EPOLL_CTL_ADD, clientfd, &ev) == -1)
 98                     ERR_EXIT("epoll_ctl");
 99             }else
100             {
101                 int nread = read(rfd, recvbuf, MAXLEN);
102                 if(nread == -1)
103                 {
104                     if(errno == EINTR)
105                         continue;
106                     ERR_EXIT("read");
107                 }else if( nread == 0)//客户端退出,从epoll轮询中删除
108                 {
109                     printf("%d fd close\n", rfd);
110                     ev.data.fd = rfd;
111                     ev.events = EPOLLIN;
112                     if(epoll_ctl(epollfd, EPOLL_CTL_DEL, rfd, &ev) == -1)
113                         ERR_EXIT("epoll_ctl");
114                 }else
115                 {
116                     if(write(rfd, recvbuf, strlen(recvbuf)) == -1)
117                         ERR_EXIT("write");
118                     memset(recvbuf, 0, MAXLEN);
119                 }
120             }
121         }
122     }
123     close(epollfd);
124 }

.poll服务器模型:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值