linux高编之TCP服务器端select函数

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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值