基本介紹
- 中文名:select()
- 外文名:select()
- 作用:多路檢測可用套接字
- 系統:Unix、Linux
- 返回:滿足條件的套接口的數目
簡述
注釋
返回值
錯誤代碼
調用
//下面是示例代碼://代碼是伺服器TCP模型,採用多路復用的select函式實現了循環的監聽並接受客戶端的功能,其中也包含了上傳下載的功能*/#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/socket.h>#include<string.h>#include<netinet/in.h>#include<sys/ioctl.h>#include<sys/stat.h>#include<fcntl.h>#include<sys/types.h>#include<dirent.h>int main(){ struct sockaddr_in seraddr,cliaddr; int listenfd,connfd,fd1,fd2,n,m,l,port; char user[20],buf[4096]; fd_set readfds,tmpfds;//崗哨監控集合 socklen_t addrlen; DIR *dr; struct dirent *file; printf("請輸入需要設定的伺服器名稱:"); scanf("%s",user); printf("請輸入需要設定的伺服器連線埠:"); scanf("%d",&port); getchar(); if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0) { perror("創建失敗"); exit(-1); } /*開始設定伺服器的參數地址類型,IP,PORT*/ memset(&seraddr,0,sizeof(seraddr));//將伺服器的初值空間清空,防止轉化過程有影響 seraddr.sin_family=AF_INET; seraddr.sin_port=htons(port);//將得到的本地連線埠轉換為網路位元組序 seraddr.sin_addr.s_addr=htonl(INADDR_ANY);//將得到的ip地址字元串轉換為網路位元組序的ip地址數值 if((bind(listenfd,(struct sockaddr*)&seraddr,sizeof(seraddr))<0)) { perror("綁定失敗"); exit(-1); } printf("綁定創建\n"); if((connfd=listen(listenfd,50))<0) { perror("監聽失敗"); exit(-1); } printf("開始監聽\n"); FD_ZERO(&readfds);//初始化檔案集 FD_SET(listenfd,&readfds);//將需要監視的listenfd放入readfds集中 while(1)//循環監聽 { int nread,n; tmpfds=readfds;//將監視集傳遞給臨時的監視集中,防止後續的操作修改了監視集 if(select(FD_SETSIZE,&tmpfds,NULL,NULL,NULL)<0)//設定監視,監視tmpfds內的子fd變化,發生變化的將會被保留在tmpfds中 { perror("監視未成功"); exit(-1); } for(fd1=0;fd1<FD_SETSIZE;fd1++)//循環找在最大範圍內的fd1 { if(FD_ISSET(fd1,&tmpfds))//查找是否fd1在tmpfds裡面 { if(fd1==listenfd)//判定fd1等於監聽fd,即監聽fd在監視過程中出現變化被發現 { addrlen=sizeof(cliaddr); connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&addrlen);//開始接收客戶 FD_SET(connfd,&readfds);//將connfd加入監視集,監視接入的變化 printf("接入新的連線\n"); } else { ioctl(fd1,FIONREAD,&nread);//測試在fd中還有nread個字元需要讀取 if(nread==0)//如果需要讀取的數據為0,則關閉檢測出來的fd1,並且從監視中移除 { close(fd1); FD_CLR(fd1,&readfds); printf("移除\n"); } else//如果可讀數據不為0,則讀出來 { int i; char *p=NULL,*q=NULL; n=read(fd1,buf,nread); buf[n]=0; p=buf; if((strncmp(p,"-get",4)==0)) { q=p+5; printf("客戶下載檔案>%s",q); if((fd2=open(q,O_RDONLY))<0) perror("打開檔案錯誤"); while((m=read(fd2,buf,4096))>0) { write(connfd,buf,m); } bzero(buf,sizeof(buf)); close(fd1); close(fd2); FD_CLR(fd1,&readfds); } if((strncmp(p,"-up",3)==0)) { q=p+4; printf("客戶上傳檔案%s\n",buf+4); if((fd2=open(q,O_CREAT | O_WRONLY | O_APPEND ,0666))<0) { perror("打開檔案寫入失敗"); } while((m=read(connfd,buf,128))>0) { printf("%s",buf); write(fd2,buf,m); } bzero(buf,sizeof(buf)); close(fd1); close(fd2); FD_CLR(fd1,&readfds); } if((strncmp(p,"-ls",3)==0)) { q=p+4; printf("客戶查看檔案……"); if((dr=opendir(q))==NULL) perror("打開目錄失敗"); while((file=readdir(dr))!=NULL) { printf("%s ",file->d_name); write(connfd,file->d_name,sizeof(file->d_name)); } close(fd1); close(connfd); closedir(dr); FD_CLR(fd1,&readfds); } printf("從客戶收取的信息:%s\n",buf); } } }//end if 0 }//end for 0 }//end while0 exit(0);}//end main
相關參考
事件用法
參數 | 描述 |
---|---|
可選。規定當 select 事件被觸發時運行的函式。 |