tcpserv程序select

利用select和poll函数来代替fork产生子进程的方法,可以实线并发连接并且可以减少fork子进程时占用的系统资源,select函数需要一个client[]数组的数据结构来维持多用户的fd,每次有新用户连接和关闭时需要对该数据结构进行更新,而poll函数是维持一个pollfd结构,比select函数方便。


select函数版:

#include "unp.h"

int main(int argc, char const *argv[])
{
	int i, maxi, maxfd, listenfd, connfd, sockfd;
	int nready, client[FD_SETSIZE];
	ssize_t n;
	fd_set rset, allset;
	char buf[MAXLINE], buff[MAXLINE];
	socklen_t clilen;
	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, (SA *) &servaddr, sizeof(servaddr));
	Listen(listenfd, LISTENQ);
	printf("---------------Waiting for connect------------\n");

	maxfd = listenfd;
	maxi = -1;
	for (i = 0; i < FD_SETSIZE; ++i)
		client[i] = -1;
	FD_ZERO(&allset);
	FD_SET(listenfd, &allset);

	for( ; ; )
	{
		rset = allset;
		nready = Select(maxfd + 1, &rset, NULL, NULL, NULL);

		if(FD_ISSET(listenfd, &rset))		/* new client connection */
		{
			clilen = sizeof(cliaddr);
			connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
			for(i = 0; i < FD_SETSIZE; i++)
				if(client[i] < 0)
				{
					client[i] = connfd;		/* save descriptor */
					break;
				}
			printf("Connect from: %s port: %d\n", 
					Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
					ntohs(cliaddr.sin_port));
			if(i == FD_SETSIZE)
				err_quit("too many clients");

			FD_SET(connfd, &allset);		/* add new descriptor to set */
			if(connfd > maxfd)
				maxfd = connfd;				/* for select */
			if(i > maxi)
				maxi = i;					/* max index in client[] array */
			if(--nready <= 0)
				continue;					/* no more readable descriptors */
		}
		for (i = 0; i <= maxi; ++i)			/* check all clients for data */
		{
			if((sockfd = client[i]) < 0)
				continue;
			if(FD_ISSET(sockfd, &rset))
			{
				if((n = Read(sockfd, buf, MAXLINE)) == 0)
				{							/* connection closed by client (FIN)*/
					Close(sockfd);
					FD_CLR(sockfd, &allset);
					client[i] = -1;			/* update client struct*/
				}
				else
					Writen(sockfd, buf, n);

				if(--nready <= 0)
					break;					/* no more readable descriptors */
			}
		}
	}
}
poll函数版:

#include "unp.h"

#define OPEN_MAX 256

int main(int argc, char const *argv[])
{
	int i, maxi, listenfd, connfd, sockfd;
	int nready;
	ssize_t n;
	char buf[MAXLINE], buff[MAXLINE];
	socklen_t clilen;
	struct pollfd client[OPEN_MAX];
	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, (SA *) &servaddr, sizeof(servaddr));
	Listen(listenfd, LISTENQ);
	printf("---------------Waiting for connect------------\n");

	client[0].fd = listenfd;
	client[0].events = POLLRDNORM;
	for(i = 1; i < OPEN_MAX; i++)
		client[i].fd = -1;
	maxi = 0;

	for( ; ; )
	{
		nready = Poll(client, maxi + 1, INFTIM);

		if(client[0].revents & POLLRDNORM)		/* new client connection */
		{
			clilen = sizeof(cliaddr);
			connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
			for(i = 1; i < OPEN_MAX; i++)
				if(client[i].fd < 0)
				{
					client[i].fd = connfd;		/* save descriptor */
					break;
				}
			printf("Connect from: %s port: %d\n", 
					Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
					ntohs(cliaddr.sin_port));
			if(i == OPEN_MAX)
				err_quit("too many clients");

			client[i].events = POLLRDNORM;
			if(i > maxi)
				maxi = i;					/* max index in client[] array */
			if(--nready <= 0)
				continue;					/* no more readable descriptors */
		}

		for (i = 1; i <= maxi; ++i)			/* check all clients for data */
		{
			if((sockfd = client[i].fd) < 0)
				continue;
			if(client[i].revents & (POLLRDNORM | POLLERR))
			{
				if((n = Read(sockfd, buf, MAXLINE)) < 0)
				{			
					if(errno == ECONNRESET)	
					{			/* connection reset by client */
						Close(sockfd);
						client[i].fd = -1;			/* update client struct*/
					}
					else
						err_sys("read error");
				}
				else if(n == 0)			/* connection closed bt client */
				{
					Close(sockfd);
					client[i].fd = -1;
				}
				else
					Writen(sockfd, buf, n);

				if(--nready <= 0)
					break;					/* no more readable descriptors */
			}
		}
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值