I/O多路复用之poll

1、poll的优缺点

poll的优点

1)poll() 不要求开发者计算最大文件描述符加一的大小。 
2)poll() 在应付大数目的文件描述符的时候速度更快,相比于select。 
3)它没有最大连接数的限制,原因是它是基于链表来存储的。

poll的缺点

1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。 
2)与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符。


2、poll服务器的简单实现

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<poll.h>
#include<string.h>

#define POLLFD_SIZE 1024
struct pollfd array_fd[POLLFD_SIZE];

void pd_action(int index)
{
	if(array_fd[index].revents & POLLIN){
		char buf[1024];
		memset(buf,0,sizeof(buf));
		ssize_t s = read(array_fd[index].fd,0,sizeof(buf)-1);
		if(s > 0){
			buf[s] = 0;
			printf("client say:%s\n",buf);
			fflush(stdout);
			array_fd[index].events = POLLOUT;
		}else{
			printf("client quit!\n");
			fflush(stdout);
			close(array_fd[index].fd);
			array_fd[index].fd = -1;//文件描述符初始化为默认值
		}
	}else if(array_fd[index].revents & POLLOUT){
		const char*msg = "HTTP/1.1 200 OK\r\n\r\n<html><br/><h1>hello poll</h1></html>";
		write(array_fd[index].fd,msg,strlen(msg));
		array_fd[index].events = POLLIN;
	}
}

int startup(const char *_ip,int _port)
{
	int sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock < 0){
		perror("socket");
		exit(1);
	}

	int opt = 1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_addr.s_addr = inet_addr(_ip);
	local.sin_port = htons(_port);
	if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
		perror("bind");
		exit(2);
	}
	if(listen(sock,10) < 0){
		perror("listen");
		exit(3);
	}
	return sock;
}

static void usage(const char *proc)
{
	printf("usage:%s[local_ip][local_port]\n",proc);
}
int main(int argc,char *argv[])
{
	if(argc != 3){
		usage(argv[0]);
		return 1;
	}

	int listen_sock = startup(argv[1],atoi(argv[2]));
	array_fd[0].fd = listen_sock;
	int i = 0;
	for(;i < POLLFD_SIZE;i++){
		array_fd[i].fd = -1;
	}

	int timeout = -1;
	while(1){
		switch(poll(array_fd,POLLFD_SIZE,timeout)){
			case 0:
				printf("timeout....\n");
				break;
			case -1:
 				perror("poll\n");
				break;
			default:
 				{
 					int j = 0;
					for(;j < POLLFD_SIZE;j++)
					{
						if(j == 0 && array_fd[j].revents & POLLIN){
							struct sockaddr_in client;
							socklen_t len = sizeof(client);
							int newfd = accept(listen_sock,(struct sockaddr*)&client,&len);
							if(newfd < 0){
 								perror("accept\n");
								continue;
							}else{
								printf("get a new client:(%s:%d)\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
								int k = 0;
								for(;k < POLLFD_SIZE;k++){
 									if(array_fd[k].fd < 0){
 										array_fd[k].fd = newfd;
										array_fd[k].events = POLLOUT;
										break;
									}
								}
								if(k == POLLFD_SIZE)
								{
 									close(newfd);
									break;
								}
							}
						}else if(j != 0){
							pd_action(j);
						}else{
						}
					}
				}
				break;
		}
	}
	close(listen_sock);
	return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值