poll函数

poll

  • 跟select类似,也是委托内核监控文件描述符,可读可写、异常事件

函数原型

int poll(struct pollfd *fds,nfds_t nfds,int timeout);
  • fds:传入传出参数,是一个结构体数组
    • fds.fd:要监控的文件描述符
    • fds.events:输入参数,要监控的事件
      • POLLIN:读事件
      • POLLOUT:写事件
      • POLLERR:异常事件
    • fds.revents:输出参数,返回事件
  • nfds:数组实际有效内容的个数,监控范围,具体是数组下标的最大值+1
  • timeout:
    • 0:不阻塞,立即返回
    • -1:表示一直阻塞,直到有事件发生
    • >0:表示阻塞的时长,在时长范围内有事件发生会立刻返回
  • 返回值:
    • >0发生变化的文件描述符个数
    • =0,超时时长,无文件描述符变化
    • -1,异常

服务器代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <errno.h>
#include "wrap.h"
#include <arpa/inet.h>
#include <ctype.h>

int main(void)
{
	
	//创建socket
	int lfd = socket(AF_INET,SOCK_STREAM,0);
	
	//设置端口复用
	int opt = 1;
	setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));
	
	//绑定
	struct sockaddr_in serv;
	serv.sin_family = AF_INET;
	serv.sin_port = htons(8888);
	serv.sin_addr.s_addr = htonl(INADDR_ANY);
	Bind(lfd,(struct sockaddr *)&serv,sizeof(serv));
	
	//监听
	Listen(lfd,128);
	
	//定义fd_set类型的变量
	fd_set readfds;
	fd_set tmpfds;//输入输出参数,输入告诉内核监控哪些文件描述符,输出告诉程序哪些文件描述符发生变化
	
	//清空readfds和tmpfds集合
	FD_ZERO(&readfds);
	FD_ZERO(&tmpfds);
	
	//将lfd加入到readfds中,委托内核监控
	FD_SET(lfd,&readfds);
	
	struct pollfd client[1024];
	client[0].fd = lfd;
	client[0].events = POLLIN;
	
	int nready = 0;
	int maxi = 0;
	int i = 0;
	int cfd = 0;
	int nbuf = 0;
	char buf[1027] = "";
	for(i = 1;i<1024;i++)
	{
		client[i].fd = -1;
	}
	maxi = lfd;
	while(1)
	{
		nready = poll(client,maxi+1,-1);
		if(nready<0)
		{
			if(errno==EINTR)
			{
				continue;
			}
			break;
		}
		
		//有客户端请求发来
		if(client[0].revents==POLLIN)
		{
		
			//接受新的客户端请求连接
			cfd = Accept(lfd,NULL,NULL);
			
			//寻找client数组中可用位置
			for(i = 0;i<1024;i++)
			{
				if(client[i].fd == -1)
				{
					client[i].fd = cfd;
					client[i].events = POLLIN;
					break;
				}
			}
			//客户端连接数达到最大值
			if(i==1024)
			{
				close(cfd);
				continue;	
			}
			if(maxi<i)
			{
				maxi = i+1;
			}		
		}
		if(nready==0)
		{
			continue;
		}
	
		//有数据发来情况
		for(i=1;i<maxi+1;i++)
		{
			//如果已经关掉,则不再监控
			if(client[i].fd==-1)
			{
				continue;
			}
			
			if(client[i].revents==POLLIN)
			{
				//读数据
				nbuf = Read(client[i].fd,buf,sizeof(buf));
				if(nbuf<=0)
				{
					close(client[i].fd);
					client[i].fd = -1;
					if(i==maxi-1)
					{
						maxi--;
					}
				}
				else
				{
					//发送数据
					Write(client[i].fd,buf,nbuf);
				}
			}	
		}
	}
	close(lfd);
	return 0;
}

总结

  • 通过数组监控文件描述符,如果fd为-1就不监控
  • 通过传出参数去得到事件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_Csyn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值