I\O复用(poll)

int poll(struct pollfd*fds,int nfds,int timeout)

struct pollfd

{

         int fd;用户关注的文件描述符

         short events;用户关注的事件

         short revents;由内核修改,表示发生了哪些

}

nfds:数组的长度 元素的个数,用户关注的文件描述符的个数

timeout:超时时间

返回值:-1出错   0超时  >0就绪文件描述符的个数

和select对比:1、用户关注的事件类型更多2、内核修改的和用户关注的分开标识,每次调用不需要重新设置3、文件描述符不再是按位来表示,直接用int类型 3.1用户关注的文件描述符的值可以更大3.2用户关注的文件描述符的个数由用户数组来决定

poll返回时,也是将用户关注的所有文件描述符返回

poll检测就绪文件描述符的时间复杂度O(n),poll返回后,用户程序依旧需要循环检测哪些文件描述符就绪。

#define  _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/select.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<poll.h>


#define SIZE 100
void Init_Fds(struct pollfd *fds)
{
    int i=0;
    for(;i<SIZE	;i++)
    {
	fds[i].fd=-1;
	fds[i].events=0;
	fds[i].revents=0;
    }
}

void Insert_Fd(struct pollfd*fds,int fd,short event)
{
    int i=0;
    for(;i<SIZE;i++)
    {
	if(fds[i].fd==-1)
	{
	    fds[i].fd=fd;
	    fds[i].events=event;
	    break;
	}
    }
}

void Delete_Fd(struct pollfd*fds,int fd)
{
    int i=0;
    for(;i<SIZE;i++)
    {
	if(fds[i].fd==fd)
	{
	    fds[i].fd=-1;
	    fds[i].events=0;
	    break;
	}
    }
}
int main()
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    assert(sockfd!=-1);


    struct sockaddr_in ser ,cli;
    memset(&ser,0,sizeof(ser));
    ser.sin_family=AF_INET;
    ser.sin_port=htons(6000);
    ser.sin_addr.s_addr=inet_addr("127.0.0.1");

    int res = bind(sockfd,(struct sockaddr*)&ser,sizeof(ser));
    assert(res!=-1);


    listen(sockfd,5);

    struct pollfd fds[SIZE];//数组
    Init_Fds(fds);//初始化
    Insert_Fd(fds,sockfd,POLLIN);//插入

    while(1)
    {
	int n=poll(fds,SIZE,-1);
	if(n<=0)
	{
	    printf("poll error\n");
	    continue;
	}
	int i=0;
	for(;i<SIZE;i++)
	{
	    if(fds[i].fd!=-1)
	    {
		int fd = fds[i].fd;
		if(fds[i].revents & POLLRDHUP)
		{
                    close(fd);
	            Delete_Fd(fds,fd);
	        }
		else if(fds[i].revents&POLLIN)//读事件就绪
		{
		    if(fd==sockfd)
		    {
			int len = sizeof(cli);
			int c = accept(fd,(struct sockaddr*)&cli,&len);
			if(c < 0)
			{
			    continue;
			}
			//printf("accpet c=%d\n",c);
			Insert_Fd(fds,c,POLLIN|POLLRDHUP);
		    }
		    else
		    {
			char buff[128]={0};
			recv(fd,buff,127,0);
			printf("%d: %s\n",fd,buff);
			send(fd,"ok",2,0);
		    }
		}
		else if(fds[i].revents & POLLRDHUP)
		{
		    close(fd);
		    Delete_Fd(fds,fd);
		}

	    }
	}
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值