栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++以select方式实现高性能网络服务器

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++以select方式实现高性能网络服务器

  

#include 
#include 
#include 
#include 
#include 

#define PORT 8111
#define MESSAGE_LEN 1024
//连接监听最大1024个,有限制
#define FD_SIZE 1024

int main(int agrc,char* argv[]){
  
    //定义两个文件描述符
    int socket_fd,accept_fd;
    int on = 1;
    int ret =-1;
    int backlog=10;//同一毫秒最大缓存连接的个数
    char in_buff[MESSAGE_LEN]={0,}; //接收消息的缓冲区
    struct sockaddr_in localaddr,remoteaddr;
    pid_t pid;
    int flags;
    //最大的文件描述符
    int max_fd = -1;
    int events = 0;
    //用于存储socket_fd的集合
    fd_set fd_sets;
    //用于存放与客户端连接的accept_fd的集合;
    int accept_fds[FD_SIZE]={-1,};

    int curpos = -1;
    //创建侦听的socket,用于创建新的socket,指的是将此变量socket_fd作为accept()方法的参数去创建accept_fd
    socket_fd = socket(AF_INET,SOCK_STREAM,0);
   
    //如果返回值为-1,则创建socket失败,直接退出
    if(socket_fd==-1){
       std::cout << "Failed to create socket!" << std::endl;
       exit(-1);
    }else{
        std::cout << "创建socket成功......" << std::endl;
    }
    //通过select方案改造:
    //获取socket_fd的flag
    flags = fcntl(socket_fd,F_GETFL,0);
    //将socket_fd设置为非阻塞
    fcntl(socket_fd,F_SETFL,flags | O_NONBLOCK);

    //设置max_fd;
    max_fd = socket_fd;
    
   //设置socket选项 
   ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR , &on ,sizeof(on));

   if (ret==-1)
   {
     std::cout << "Failed to set socket options!" << std::endl;
   }else{
        std::cout << "socket选项设置成功......" << std::endl;
    }

   //为结构体赋值
   localaddr.sin_family = AF_INET;
   localaddr.sin_port =PORT;
   localaddr.sin_addr.s_addr=0;
   bzero(&(localaddr.sin_zero),8);
   //如果绑定失败就退出,服务无法启动
   ret = bind(socket_fd,(struct sockaddr*)&localaddr,sizeof(struct sockaddr));
   if (ret==-1)
   {
      std::cout << "Failed to set bind addr!" << std::endl;
      exit(-1);
   }else{
        std::cout << "socket地址、端口绑定成功......" << std::endl;
   }

   ret = listen(socket_fd,backlog);
   if (ret==-1)
   {
      std::cout << "Failed to listen socket!" << std::endl;
      exit(-1);
   }else{
        std::cout << "socket监听创建成功,监听客户端连接中......" << std::endl;
   }

   
   for (;;){
     //通过宏对fd_sets的集合进行清空
     FD_ZERO(&fd_sets);
     FD_SET(socket_fd,&fd_sets);
     for (int i = 0; i < FD_SIZE; i++){
        if (accept_fds[i]!= -1){
          if (accept_fds[i]>max_fd){
            max_fd = accept_fds[i];
          }
          //将存储accept_fd的集合设置到fd_sets集合中
          FD_SET(accept_fds[i],&fd_sets);
        }
     }
     
     //max_fd+1 :最大的文件描述符加1
     events = select(max_fd+1,&fd_sets,NULL,NULL,NULL);

     if (events<0){
      std::cout << "failed to use select!" << std::endl;
      break;
     }else if (events == 0){
       std::cout << "timeout......!" << std::endl;
       continue;
     }else if(events){
      //如果是客户端请求的连接来了
      if (FD_ISSET(socket_fd,&fd_sets)){
        //在accept_fds[i]集合中找一个没存储过accept_fd的位置,记录下标
        for (int i = 0; i < FD_SIZE; i++){
          if (accept_fds[i]==-1){
            curpos=i;
            break;
          }
        }
        //循环等待客户端连接
        socklen_t addr_len =sizeof(struct sockaddr);
        accept_fd = accept(socket_fd,(struct sockaddr *) &remoteaddr,&addr_len);
        //获取socket_fd的flag
        flags = fcntl(accept_fd,F_GETFL,0);
        //将socket_fd设置为非阻塞
        fcntl(accept_fd,F_SETFL,flags | O_NONBLOCK);
        
        //存入等待连接的集合中
        accept_fds[curpos] = accept_fd;
      }
      //如果是客户端的数据来了
      for (int i = 0; i < FD_SIZE; i++)
      {
        //如果accept_fds[i]不等于-1,并且accept_fds[i]在&fd_sets集合中
        if(accept_fds[i] != -1 && FD_ISSET(accept_fds[i],&fd_sets)){
              //循环接收数据
              memset(in_buff,0,MESSAGE_LEN);
              ret = recv(accept_fds[i],(void *)in_buff,MESSAGE_LEN,0);
              if (ret==0)
              {
                close(accept_fds[i]);
                break;
              }
              std::cout << "recv:来自客户端消息=> :" << in_buff << std::endl;
              //将接收到的客户端信息回显给客户端
              send(accept_fds[i],(void *)in_buff,MESSAGE_LEN,0);
        }
      } 
    }  
  }
  close(socket_fd);
  return 0;

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1012634.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号