I/O复用—poll


由于poll和select非常相似,对于其理论内容就不过多介绍,我们直接看其系统调用接口。

poll系统调用

poll的原型

#include<poll.h>
int poll(struct pollfd,nfds_t nfds,int timeout);
  • fds参数:一个pollfd结构类型的数组,指定所有我们希望监听的所有文件描述符上发生的可读、可写和异常等事件。

  • pollfd结构体

struct pollfd
{
	int     fd;    //文件描述符
	short  events;  //注册的事件
	short  revents;//实际发生的事件,由内核填充
}
  • fd:指定文件描述符
  • events:告诉poll监听fd上的哪些事件,它是一系列事件的按位或
  • revents:由内核修改,用来通知fd上哪些事件就绪了
    如果events上的事件发生了,revents就会将自己与events的对应位置为1

poll事件类型
在这里插入图片描述

  • nfds:指定被监听事件集合fds的大小。
typedef  unsigned  long int  nfds_t;
  • timeout:指定poll的超时值,单位是毫秒。
    当timeout 为-1时,poll调用将永远阻塞,直到某个事件发生
    当timeout为0时,poll调用将立即返回

poll举例

ser

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

#define MAXFD 10
int create_sockfd();

void fds_add(struct pollfd fds[],int fd)
{
	int i=0;
	for(;i<MAXFD;++i)
	{
		if(fds[i].fd==-1)
		{
			fds[i].fd=fd;
			fds[i].events=POLLIN;
			fds[i].revents=0;
			break;
		}
	}

}

void fds_del(struct pollfd fds[],int fd)
{
	int i=0;
	for(;i<MAXFD;++i)
	{
		if(fds[i].fd==fd)
		{
			fds[i].fd=-1;
			fds[i].events=0;
			fds[i].revents=0;
			break;
		}
	}
}

void fds_init(struct pollfd fds[])
{
	int i=0;
	for(;i<MAXFD;++i)
	{
		fds[i].fd=-1;
		fds[i].events=0;
		fds[i].revents=0;
	}
}
int main()
{
	int sockfd=create_sockfd();
	assert(sockfd!=-1);

	 struct pollfd  fds[MAXFD];
     fds_init(fds);

	 fds_add(fds,sockfd);

	 while(1)
	 {
		int n=poll(fds,MAXFD,5000);
		if(n==-1)
		{
			perror("poll error");
		}
		else if(n==0)
		{
			printf("time out\n");
		}
		else
		{
			int i=0;
			for(;i<MAXFD;++i)
			{
				if(fds[i].fd==-1)
				{
					continue;
				}

			if(fds[i].revents &POLLIN)//have data
			{
				if(fds[i].fd==sockfd)
				{
					struct sockaddr_in caddr;
					int len=sizeof(caddr);

					int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
					if(c<0)
					{
						continue;
					}
					printf("accept c=%d\n",c);
					fds_add(fds,c);//join
				}
				else
				{
					char buff[128]={0};
					int res=recv(fds[i].fd,buff,127,0);
					if(res<=0)
					{
						close(fds[i].fd);
						fds_del(fds,fds[i].fd);
						printf("one client over\n");
					}
					else
					{
						printf("recv(%d)=%s\n",fds[i].fd,buff);
						send(fds[i].fd,"ok",2,0);
					}
				}
			}
	   	}
		}
	 }

}

int create_sockfd()
{
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd==-1)
	{
		return -1;
	}

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

	int res=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
	if(res==-1)
	{
		return -1;
	}

	listen(sockfd,5);

	return sockfd;
}

select和poll的区别

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43313035/article/details/89392446