Linux 高性能服务器编程——I/O复用 poll

23 篇文章 0 订阅

一:poll系统调用

  同select相似,也是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者。

二:poll函数

  1.函数原型:

#include<poll.h>

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

  2.函数参数:

    先来了解一下struct pollfd这个结构体

 

struct pollfd
{
    int fd;            //文件描述符
    short events;      //注册的事件
    short revents;     //实际发生的事件,由内核填充。
}
/*其中fd成员指定文件描述符;events成员告诉poll监听fa上的那些事件,它是一系列事件的按位或;
  revents则有内核修改,以通知应用程序fd上实际发生了那些事件。*/
①fds:pollfd结构类型的数组,指定我们所有感兴趣的文件描述符上发生的可读,可写,异常等事件。
②ndfs:指定被监听事件集合fds的大小。(其类型位:typedef unsigned long int nfds_t;)
③timeout:

设置超时时间,单位毫秒。

-1:poll将永远阻塞

0:poll调用将立即返回。

三:逻辑思想

四:测试代码

 

服务器端:

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

#define SIZE 100
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;
				//		fds[i].revents = 0;
				}
		}
}
void Init_fd(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;
				}
		}
}
		
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_fd(fds);
		Insert_fd(fds,sockfd,POLLIN);

		while(1)
		{
				int n = poll(fds,SIZE,-1);
				if(n<=0)
				{
						printf("poll fail!!!\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);
										printf("%d: will close\n",fd);
								}
								else if(fds[i].revents & POLLIN)
								{
										if(fd == sockfd)
										{
												int len = sizeof(cli);
												int c = accept(sockfd,(struct sockaddr*)&cli,&len);
												if(c<=0)
												{
														printf("accept is fail\n");
														continue;
												}
												
												Insert_fd(fds,c,POLLIN|POLLRDHUP);
												
										}
										else
										{
												char buff[128]={0};
												int n =recv(fds[i].fd,buff,127,0);
												if(n<=0)
												{
														close(fds[i].fd);
														Delete_fd(fds,fds[i].fd);
														printf("%d: is close\n",fd);
												}
												else
												{
														printf("%d: %s\n",fd,buff);
														send(fd,"OK",2,0);
												}

										}
								}
						}
				}

		}

	close(sockfd);

}

客户端:

#include"../../apue.h"
int main()
{
		int sockfd = socket(AF_INET,SOCK_STREAM,0);
		assert(sockfd != -1);
		struct sockaddr_in ser;
		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 = connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));
		assert(res != -1);
		
		while(1)
		{
				printf("please input:\n");
				fflush(stdout);

				char buf[128]={0};
				fgets(buf,127,stdin);
				buf[strlen(buf)-1] = 0;

				if(strcmp(buf,"end") == 0)
				{
						break;
				}
				send(sockfd,buf,strlen(buf),0);
				printf("send is OK\n");

			//	char recvbuff[128] = {0};
			//	recv(sockfd,recvbuff,127,0);
			//	printf("%s:\n",recvbuff);
		}
		close(sockfd);
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值