#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; }



