Linux复用I/O-poll-server代码

poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。

poll
#include
int poll( struct pollfd *fds, nfds_t nfds, int timeout );//第一个参数,传入的是一个结构体数组。

struct pollfd {
int fd; /* 文件描述符*/
short events; /* 监控的事件*/
short revents; /* 监控事件中满足条件返回的事件*/
};

//监控事件的类型
POLLIN普通或带外优先数据可读,POLLRDNORM | POLLRDBAND
POLLRDNORM-数据可读
POLLRDBAND-优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT普通或带外数据可写
POLLWRNORM-数据可写
POLLWRBAND-优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件

nfds 监控数组中有多少文件描述符需要被监控
timeout 毫秒级等待
-1:阻塞等,#define INFTIM -1 Linux中没有定义此宏
0:立即返回,不阻塞进程
>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1poll不再监控此
pollfd,下次返回时,把revents设置为0
ppoll GNU定义了ppoll(POSIX标准),可以支持设置信号屏蔽字,大家可参考poll模型自行实现C/S

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define SERVER_PORT	8000
#define LISTEN_LEN	128
#define BUF_SIZE	1500
#define FD_MAX		1024
//select 最大限制1024
int main(int argc , char * argv[])
{
	struct sockaddr_in serveraddr,clientaddr;
	int maxfd,flag,ready;//maxfd打开的最大文件描述符,flag是client数组中有内容的最大下标,ready存放有事件发生的个数
	int listenfd,clientfd,tempfd;
	int cliaddr_len,len;
	int i,j;
	char ipstr[128],buf[BUF_SIZE];
	struct pollfd cliARR[FD_MAX];
	/*创建socket*/
	listenfd = socket(AF_INET,SOCK_STREAM,0);
	/*初始化bzero*/
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serveraddr.sin_port = htons(SERVER_PORT);
	/*绑定bind()*/
	bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	listen(listenfd,LISTEN_LEN);
	cliARR[0].fd = listenfd;
	cliARR[0].events = POLLRDNORM;//listen监听事件
	for(i = 1;i
		//判断listenfd是否有数据到达
			cliaddr_len = sizeof(clientaddr);
			clientfd = accept(listenfd,(struct sockaddr*)&clientaddr,&cliaddr_len);
			printf("client IP:%s\tPORT:%d\n",
					inet_ntop(AF_INET,
						&clientaddr.sin_addr,
						ipstr,
						sizeof(ipstr)),
						ntohs(clientaddr.sin_port));
			for(i = 1;iflag)
				flag = i;
			if(--ready == 0)
				continue;
		}
		//接收普通socket的数据
		for(i=1;i<=flag;i++){
			if((tempfd = cliARR[i].fd)<0)
				continue;
			if(cliARR[i].revents&(POLLRDNORM | POLLERR)){
				if((len = read(tempfd,buf,sizeof(buf)))<0){
					if(errno == ECONNRESET){
					close(tempfd);
					cliARR[i].fd=-1;
					}else{
					perror("read ERROR");
					exit(-1);
					}
				}else if(len == 0){
					close(tempfd);
					cliARR[i].fd=-1;
				}else{
					for(j = 0;j



你可能感兴趣的:(c)