#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc,char **argv)
{
int i,maxi,maxfd,listenfd,connfd,sockfd;
int nready,client[FD_SETSIZE];
ssize_t n;
fd_set rset,allset;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
socklen_t cliaddr_len;
struct sockaddr_in cliaddr,servaddr;
listenfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(SERV_PORT);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
listen(listenfd,20);
maxfd=listenfd;
maxi=-1;
for(i=0;i<FD_SETSIZE;i++) //初始化client[]为-1,
client[i]=-1;
FD_ZERO(&allset); //清空allset
FD_SET(listenfd,&allset); //把listenfd描述符添加到allset文件描述符集中
for(;;){
rset=allset; //每次调用select函数后,函数返回的rset中存放的都是已就绪的描述符,描述符集内任何未就绪的对应位都被清0,所以在每次调用select之前都要重新再次把相关的描述符置位
nready=select(maxfd+1,&rset,NULL,NULL,NULL); //select返回已就绪的描述符个数,存在nreay中
if(nready<0)
printf("select error\n");
if(FD_ISSET(listenfd,&rset)){ //判断listenfd是否已就绪
cliaddr_len=sizeof(cliaddr);
connfd=accept(listenfd,(struct sockaddr *)&cliaddr,&cliaddr_len); //sercer与client建立连接,将新的描述符给connfd;
printf("recrived from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),ntohs(cliaddr.sin_port));
for(i=0;i<FD_SETSIZE;i++) //将已连接的client描述符存放在client中
if(client[i]<0){
client[i]=connfd;
break;
}
if(i==FD_SETSIZE){
fputs("too many clients\n",stderr);
exit(1);
}
FD_SET(connfd,&allset); //将client描述符写进allset文件描述符集中
if(connfd>maxfd)
maxfd=connfd; //把最新的描述符保存在maxfd中
if(i>maxi)
maxi=i; //把连接个数保存在maxi中
if(--nready==0)
continue; //若文件描述符已读完,结束此次循环
}
for(i=0;i<=maxi;i++){
if((sockfd=client[i])<0) //若client描述符集中没有连接,则结束
continue;
if(FD_ISSET(sockfd,&rset)){ //判断sockfd是否已连接就绪
if((n=read(sockfd,buf,MAXLINE))==0){ //判断client是否终止
close(sockfd); // 若client终止,则关闭客户端描述符
FD_CLR(sockfd,&allset); //将client描述符在addset文件描述符集中清楚
client[i]=-1; //同时将相应的client位设置初值-1
}else{ //若client没有终止,则与client通信
int j;
for(j=0;j<n;j++)
buf[j]=toupper(buf[j]);
write(sockfd,buf,n);
}
if(--nready==0) //判断是否有client写入数据,若没有则结束本次循环
break;
}
}
}
}
linux高编之TCP服务器端select函数
最新推荐文章于 2022-06-13 09:31:17 发布