#define PORT 1234 #define BACKLOG 5 #define MAXDATASIZE 1000 typedef struct CLIENT{ int fd; char* name; struct sockaddr_in addr;//addr用client_addr更加准确 char*data; }; void main(){ int i,maxi,maxfd,sockfd; in nready; fd_set rset,allset;//allset是我们要监控的fd集合,由于每次调用select都会更改监控的fd集合状态,所以再次调用的时候,需要重新设置fd集合,这里可以用allset保持监控集合,每次调用的时候用rset。改变的只是rset ssize_t n; int listenfd.connfd; struct sockaddr_in server_addr, client_addr;//注意,这里我们把client端的信息保存在CLIENT结构体中, CLIENT client[FD_SETSIZE];//FD_SETSIZE是宏常量 char buf[MAXDATASIZE]; int sin_size; if(listenfd=socket(AF_INET,SOCK_STREAM,0)==-1){ perror("create socket failed"); exit(1); } bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(PORT); server_addr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listenfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)==-1) { perror("bind socket failed"); exit(1); } if(listen(listenfd,BACKLOG)==-1) { perror("listen socket failed"); exit(1); } sin_size=sizeof(struct sockaddr_in) maxfd=listenfd;//最大的文件描述符 maxi=-1; //最大的用过的CLIENT数组下标 for(i=0;i<FD_SETSIZE;i++){ client[i].fd=-1; }//初始化client数组 FD_ZERO(&allset); FD_SET(listenfd,&allset);//加入监听 while(1){ struct sockaddr_in addr; //用于返回client端的信息 rset=allset;// 再次重新赋值 nready=select(maxfd+1,&rset,NULL,NULL,NULL)//这测试FD读就绪,写的fdset为NULL if(FD_ISSET(listenfd,&allset)){ //new client connection if((connfd=accept(listenfd,(struct sockaddr*)&addr,&sin_size))==-1) { perror("accept() error\n"); exit(1); continue; } for(i=0;i<FD_SETSIZE;i++) if(client[i].fd<0){ client[i].fd=connfd; client[i].name=new char[MAXDATASIZE]; client[i].addr=addr;//客服端的socket地址信息 printf(" you got a connection from client"); break; } if(i==FD_SETSIZE) printf("too many connection")//;连接数的FD已经超过最大的1024 FD_SET(connfd,&allset);//把connfd加入监听集合中 if(connfd>maxfd) maxfd=connfd;//更新目前最大的FD; if(i>maxi) maxi=i; if(--nready<=0) continue;//之前select返回的时候只有一个监听listen是就绪的,则继续循环while(1),下面的程序不执行 } //对应 if(FD_ISSET(listenfd,&allset)) for(i=0;i<=maxfd;i++){ if((sockfd=client[i].fd<0)) continue; if(FD_ISSET(sockfd,&rset)){//分两种情况,一种是此FD由于关闭连接,而变成可读 if( (n=recv(sockfd,recvbuf,MAXDATASIZE,0))==0){ close(sockfd);//关闭这个连接对应服务器的连接socket FD_CLR(sockfd,&allset);//从监控的FD集合中删除 .................. ................... } else process(&client[i],revbuf,n)//否则就是读就绪,进行我们的操作 if(--nready<=0) break;//处理完了所有的就绪描述符 } } } close(listenfd);//调出while }
时间: 2024-11-07 11:05:57