Linux c++(socket网络通信 & epoll 边沿非阻塞)

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

 int main(int argc,char *argv[]){
      struct sockaddr_in serv_addr;
      socklen_t serv_len = sizeof(serv_addr);
      //    int port = atoi(a);
      //创建套接字
      int lfd = socket(AF_INET,SOCK_STREAM,0);
      //初始化服务器
      memset(&serv_addr,0,serv_len);
      serv_addr.sin_family=AF_INET;
      serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
      serv_addr.sin_port = htons(8888);
      //绑定IP和端口
      bind(lfd,(struct sockaddr*)&serv_addr,serv_len);
      //设置同时监听的最大个数                                                 
      listen(lfd,36);
      printf("Start accept ......\n");

      struct sockaddr_in client_addr;
      socklen_t cli_len = sizeof(client_addr);

      // 创建epoll树根节点
      int epfd = epoll_create(1);
      // 初始化
      struct epoll_event ev;
      // ev.events = EPOLLIN;
      ev.events = EPOLLIN | EPOLLET;
      ev.data.fd = lfd;
      epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);

      struct epoll_event all[2000];
      while(1)
      {
          // 使用epoll通知内核fd 文件IO检测
          int ret = epoll_wait(epfd,all,sizeof(all)/sizeof(all[0]),-1);
          if(ret == -1)
          {
              perror("epoll_wait error");
              break;
          }else if(ret == 0)
          {
              continue;
          }else{ // 有变化
              // 便利all数组是否有新连接
              for(int i = 0;i<ret;++i)
              {
                  int fd = all[i].data.fd;
                  // 判断是否有新链接,并且读事件变化
                  if(fd == lfd && all[i].events & EPOLLIN)
                  {
                      int cfd = accept(lfd,(struct sockaddr*)&client_addr,&cli_len);
                      // 这是cfd为非阻塞
                      int flags =fcntl(cfd,F_GETFL);
                      flags |= O_NONBLOCK;
                      fcntl(cfd,F_SETFL,flags);
                      if(cfd == -1)                                            
                      {
                          perror("accept error");
                          continue;
                      }
                      // 将新cfd挂载到树上
                      ev.events = EPOLLIN;
                      ev.data.fd = cfd;
                      epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);
                  }else if(all[i].events & EPOLLIN){ //cfd变化,而且是读事件变>
                      while(1)
                      {
                          // 处理已经连接的客户端发来的数据
                          char buf[4] = {0};
                          int len = recv(fd,buf,sizeof(buf),0);
                          if (len <0) {
                              if(errno == EAGAIN)
                                  break;
                              perror("recv error");
                              close(fd);
                              epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&all[i]);
                              continue;
                          }else if(len == 0)
                          {
                              printf("客户端断开连接\n");
                              close(fd);
                              epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&all[i]);
                              break;
                          }else{
  //    printf("recv %s\n",buf);
                              write(STDOUT_FILENO,buf,4);
  //                            write(fd,buf,len);
                              send(fd,buf,len,0);
                          }   
                      }   
                  }   
              }   
          }   
      }   
      close(lfd);
      return 0;
  }

posted on 2021-05-22 16:12  lodger47  阅读(202)  评论(0)    收藏  举报

导航