標籤:
#define PORT 1234#define BACKLOG 5#define MAXDATASIZE 1000typedef 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}
linux select代碼架構