《UNIX网络编程 卷1》 笔记: 使用poll函数的单进程TCP回显服务器程序

本节我们使用poll函数来实现单进程TCP回显服务器。poll函数与select函数不同,它不使用描述符集,而是使用pollfd结构体数组,pollfd结构体如下:

 

struct pollfd {
   int   fd;         /* file descriptor */
   short events;     /* requested events */
   short revents;    /* returned events */
};

events表示该描述符感兴趣的事件,revents表示在该描述符上发生的事件,各种事件定义如下:

 

《UNIX网络编程 卷1》 笔记: 使用poll函数的单进程TCP回显服务器程序_第1张图片

我们定义一个1024大小的pollfd结构体数组,传递给poll函数,poll函数会监听数组里所有有效的描述符。每次一个新的客户连接时,我们为其分配数组中的一项,fd设置为客户套接字描述符,events设置为POLLRDNORM,然后循环处理所有的事件。代码如下:

 

#include "unp.h"

#define OPEN_MAX 1024

int main(int argc, char **argv)
{
	int i, maxi, listenfd, connfd, sockfd;
	int nready;
	ssize_t n;
	char buf[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);

	client[0].fd = listenfd; /*监听服务器socket*/
	client[0].events = POLLRDNORM;
	for (i = 1; i < OPEN_MAX; i++) /*任何fd为负值的项都被poll忽略*/
		client[i].fd = -1;
	maxi = 0;
	for ( ; ; ) {
		nready = Poll(client, maxi + 1, -1);
		if (client[0].revents & POLLRDNORM) { /*新的客户连接*/
			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;
					break;
				}
			}
			if (i == OPEN_MAX)
				err_quit("too many clients");
			client[i].events = POLLRDNORM;
			if (i > maxi)
				maxi = i;
			if (--nready <= 0)
				continue;
		}
		for (i = 1; i <= maxi; i++) {
			if ((sockfd = client[i].fd) < 0)
				continue;
			if (client[i].revents & (POLLRDNORM | POLLERR)) {
				if ((n = read(sockfd, buf, MAXLINE)) < 0) {
					if (errno == ECONNRESET) { /*客户复位连接*/
						Close(sockfd);
						client[i].fd = -1;
					} else
						err_sys("read error");
				} else if (n == 0) { /*客户关闭连接*/
					Close(sockfd);
					client[i].fd = -1;
				} else
					Writen(sockfd, buf, n);

				if (--nready <= 0)
					break;
			}
		}
	}
}

 

 

 

你可能感兴趣的:(UNIX网络编程,卷1,Linux,网络编程,poll)