这里你得尝试理解一下select函数
select是个古老的函数。在古老的UNIX系统里面,希望用单线程处理阻塞的网络函数,比如accept, recv, send,怎么办呢?于是我们的程序员老祖宗们发明了伟大的select函数。
首先,考虑到我们的socket是一个一个的文件流(这一点很重要),于是我们设计了FD_SET这个宏,把socket和状态级fd_set readfd, writefd, errorfd捆绑起来,用select函数定时轮循,限制这个函数操作在一个时间片内返回,将返回结果逐一核对,分别检查accept/recv/send有关的socket是不是动作了,如果有数据或者有结果采取处理,否则操作系统可以空闲下来干点别的:
fd_set readfd;
FD_ZERO(&readfd);
FD_SET(sockfd,&readfd);
while(1){
sin_size=sizeof(struct sockaddr_in);
/*select,第一个参数是用于检查所有socket,第二个参数检查缓冲测试区,第三个第四个也是,顺序是readfd, writefd和errorfd,最后一个参数是限制select检查用的等待时间*/
if(select(MAX_CONNECTED_NO,&readfd,NULL,NULL,(struct timeval *)0)> 0){
if(FD_ISSET(sockfd,&readfd)> 0){ /*可以进行accept了,直接放进来*/
if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1){
perror( "accept ");
exit(1);
}
/*可以读取数据了*/
if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))==-1){
perror( "recv ");
exit(1);
}
if(read(client_fd,buf,MAXDATASIZE) <0){
perror( "read ");
exit(1);
}
printf( "received a connection :%s ",buf);
}/*if*/
close(client_fd);
}/*select*/
}/*while*/
这样,服务器可以不需要多线程、多进程就完成了所有socket的各种操作,比如accept,recv和send。令人惊讶的是,这样写的服务器程序稳定性和效率都远高于现在我们用的CreateProcess/CreateThread/fork/pthread_creaet等等,前辈的能耐真是让我们汗颜啊!
但愿你看明白了
转载于:https://my.oschina.net/u/4000302/blog/3043530