linux多路转接select---服务器代码
一、linux多路转接select---服务器代码
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<sys/time.h> #include<arpa/inet.h> int main(int argc,const char* argv[]) { if(argc<2) { printf("please input ./a.out port\n"); return 0; } int port=atoi(argv[1]);//argv[1],从命令行输入端口号 //1、socket创建套接字 int lfd=socket(AF_INET,SOCK_STREAM,0); if(lfd==-1) { perror("socket error"); return -1; } //2、bind绑定端口号,ip struct sockaddr_in ser_addr;//创建结构体存储使用协议,ip地址、端口号 ser_addr.sin_family=AF_INET;//ipv协议 ser_addr.sin_port=htons(port);//设置端口 ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);//监听本机所有ip int ret=bind(lfd,(struct sockaddr*)&ser_addr,sizeof(ser_addr)); if(ret==-1) { perror("bind error"); return -1; } //3、listen监听 listen(lfd,128); //4、创建文件描述符表,并初始化,将监听的lfd加入到读集合中 fd_set readfds,tempfds; FD_ZERO(&readfds); FD_SET(lfd,&readfds); int maxfd=lfd;//记录文件描述符集中当前最大的文件描述符 //5、循环委托内核检测 struct sockaddr_in cli_addr; socklen_t cli_addr_len=sizeof(cli_addr); while(1) { tempfds=readfds; int num=select(maxfd+1,&tempfds,NULL,NULL,NULL);//第三个NULL,永久阻塞 if(num==-1) { perror("select error"); exit(1); } if(FD_ISSET(lfd,&tempfds))//有新的连接请求,select退出阻塞,清空tempfds中没有连接请求的文件描述符;FD_ISSET检测lfd文件描述符是否在tempfds文件描述符集中 { int cfd=accept(lfd,(struct sockaddr*)&cli_addr,&cli_addr_len);//接收连接 if(cfd==-1) { perror("accept error"); exit(1); } //将cfd加入到文件描述符集readfds中 FD_SET(cfd,&readfds); //更新最大的文件描述符 maxfd=maxfd>cfd?maxfd:cfd; //打印新连接的客户端ip和port号 char ip[16]; memset(ip,0,sizeof(ip)); const char* addr_dst=inet_ntop(AF_INET,&cli_addr.sin_addr.s_addr,ip,sizeof(ip));//将客户端IP转换为字符串形式存储到ip中 printf("client IP:%s,port:%d,connect sucessful\n",addr_dst,ntohs(cli_addr.sin_port));//将端口号从网络字节顺序转换到本机字节顺序(无符号短整型) } //循环判断客户端时候发送数据 for(int i=lfd+1;i<=maxfd;++i) { if(FD_ISSET(i,&tempfds))//如果客户端发送数据 { char buf[1024]; //读数据 memset(buf,0,sizeof(buf)); int n=read(i,buf,sizeof(buf)); if(n<0) { printf("read error"); exit(1); }else if(n==0) { printf("client disconnect\n"); close(i); FD_CLR(i,&readfds); }else{ printf("recv buf:%s\n",buf); //写数据 write(i,buf,sizeof(buf)); } } } } close(lfd); return 0; }
注:select多路转接的意义,以及解题思路后续补上(见谅)
二、运行截图
1、服务器运行截图

2、客户端A、B运行截图

注:192.127.50.128是我电脑的ip地址,你可以用ifconfig查看自己电脑的ip地址,然后替换
127.0.0.1是本机的回送地址,一般用于测试使用
nc命令+ip(本机回收ip或电脑ip)+端口号可以模拟客户端用于测试
一入编程深似海、多学多查多动手

浙公网安备 33010602011771号