#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
}