poll实现I/O多路复用

函数原型:



函数说明:该函数允许进程指示内核等待多个事件中的任何一个发生,并只在有一个或多个事件发生的时候才。

唤醒它

参数说明:

fds:是一个struct pollfd 结构体类型的数组,用于存放需要检测其状态的socket描述符。

每当调用这个函数之后,系统不会清空这个数组,特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,在调用select之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()函数之后,必须把select描述符重新加入到待检测的集合中;因此,select()函数适用于select描述符较少且相距较近的情况。

nfds:用于标记fds中的结构体元素的总数量

timeout:poll函数的阻塞时间,单位是毫秒

1、timeout  ==  0,poll立即返回不阻塞

2、timeout  > 0,阻塞的毫秒数

3、timeout == -1,poll一直阻塞,直到所检测的socket描述符上的感兴趣的事件发生才返回。

返回值:

1、 > 0:数组fds中准备就绪的socket描述符总量

2、== 0:超时

3: -1:出错

poll与select不同在于描述符存储方式不同和参数类型不同。

1.结构体数组的管理:当每次有需要关心的描述符时,将其放入结构体中,每次有无效的描述符后,将其描述符置-1,下次poll函数会忽略它。当有新的描述符加入时,从头遍历结构体,将为-1的元素设为要关心的描述符事件状态。切记:当新的描述符加到结构体数组末尾时要更新关心描述符个数,即poll第二个参数。

2.每次调用poll后,结构体元素revents会存储就绪事件状态,当每次重新调用poll之前时,系统会自己设置其为0,重新监听关心事件(不需要用户重新置0)

3.poll中参数不是输入,输出型,因此timeout,struct pollfd *fds参数不需重置,nfds看情况(参照第一点),而select函数是输入输出类型,每次调用前需重置。

实现IO复用:关心输入输出条件就绪:

/*************************************************************************
	> File Name: poll.c
	> Author: fucang_zxx
	> Mail: fucang_zxx@163.com 
	> Created Time: 2016年08月01日 星期一 13时41分06秒
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>

int main(int argc, char* argv[])
{
	if(argc != 3)
	{
		printf("Usage #: %s [ip] [port]\n", argv[0]);
		exit(1);
	}

	//创建数组,用以指定我们感兴趣的文件描述符上发生的可读、可写和异常等事件
	//struct pollfd
	//{
	//	int fd;  /*文件描述符*/
	//	short events; /*注册的事件*/
	//	short revents; /*实际发生的事件,由内核填充,输出型*/
	//};
	struct pollfd fds[2];
	fds[0].fd = 0;
	fds[0].events = POLLIN; /*对读事件感兴趣*/
	fds[0].revents = 0; /*输出型*/

	fds[1].fd = 1;
	fds[1].events = POLLOUT; /*对写事件感兴趣*/
	fds[1].revents = 0;

	char buf[1024];
	int done = 0;
	int i = 0;

	int timeout = 5000; /*5000毫秒数,即5秒*/

	while(!done)
	{
		int ret = poll(fds, sizeof(fds)/sizeof(fds[0]), timeout);
		switch(ret)
		{
			case -1:
				perror("poll");
				exit(2);
				break;
			case 0:
				printf("timeout...\n");
				break;
			default:
				//有事件就绪,但还需判断是哪个文件描述符的什么事件
				//int i = 0;
				for(i = 0 ; i < sizeof(fds)/sizeof(fds[0]); ++i)
				{
					//是否可读
					//fds[i]所关心的事件是读,而且有读事件发生
					if( fds[i].fd == 0 && (fds[i].revents & POLLIN) )
					{
						memset(buf, '\0', sizeof(buf));
						ssize_t _s = read(0, buf, sizeof(buf) - 1);
						if(_s > 0)
						{
							buf[_s - 1] = '\0';
							if(strncmp(buf, "quit", 4) == 0)
							{
								close(fds[i].fd);
								exit(0);
							}
							printf("echo#: %s\n", buf);
						}
						
					}
					/*注意:标准输出一直成立*/
					else if( fds[i].fd == 1 & (fds[i].revents & POLLOUT) )
					{
						memset(buf, '\0', sizeof(buf));
						strcpy(buf,"hello fucang");
						printf("echo#: %s\n", buf);
					}
					
				}
				break;
		}
	}

	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值