成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

I/O多路轉(zhuǎn)接 ---- poll

一、poll

創(chuàng)新互聯(lián)建站專注于網(wǎng)站建設(shè)|成都網(wǎng)站改版|優(yōu)化|托管以及網(wǎng)絡(luò)推廣,積累了大量的網(wǎng)站設(shè)計與制作經(jīng)驗,為許多企業(yè)提供了網(wǎng)站定制設(shè)計服務(wù),案例作品覆蓋濕噴機等行業(yè)。能根據(jù)企業(yè)所處的行業(yè)與銷售的產(chǎn)品,結(jié)合品牌形象的塑造,量身設(shè)計品質(zhì)網(wǎng)站。

    poll的實現(xiàn)和select非常相似,只是描述fd集合的方式不同,poll使用pollfd結(jié)構(gòu)而不是select的fd_set結(jié)構(gòu),其他的都差不多。

二、poll相關(guān)函數(shù)

#include <poll.h>

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

//fds: pollfd結(jié)構(gòu)體 

     events: 要監(jiān)視的事件 

     revents: 已經(jīng)發(fā)生的事件,  設(shè)置標(biāo)志 來反映相關(guān)條件的存在

                常量                                 說明

            POLLIN                           普通或優(yōu)先級帶數(shù)據(jù)可讀

            POLLRDNORM              普通數(shù)據(jù)可讀

            POLLRDBAND               優(yōu)先級帶數(shù)據(jù)可讀

            POLLPRI                        高優(yōu)先級數(shù)據(jù)可讀

            POLLOUT                      普通數(shù)據(jù)可寫

            POLLWRNORM             普通數(shù)據(jù)可寫

            POLLWRBAND              優(yōu)先級帶數(shù)據(jù)可寫

            

            // 只能作為描述字的返回結(jié)果存儲在revents中

            POLLERR                      發(fā)生錯誤

            POLLHUP                      發(fā)生掛起

            POLLNVAL                    描述字不是一個打開的文件

struct pollfd 
{    int   fd;         /* 文件描述符 */ 
     short events;     /* 請求的事件 */   
     short revents;    /* 返回的事件 */  
};

//nfds: 要監(jiān)視的描述符的數(shù)目

//timeout:指定poll在返回前沒有接收事件時應(yīng)該等待的時間【單位:ms】。   

        INFTIM: 永不超時

        0 :立即返回

        >0: 等待指定的時間

2、特點:

    pollfd并沒有最大數(shù)量限制(但是數(shù)量過大后性能也是會下降)。

    和select函數(shù)一樣,poll返回后,需要輪詢pollfd來獲取就緒的描述符。

    select和poll都需要在返回后,通過遍歷文件描述符來獲取已經(jīng)就緒的socket。事實上,同時連接的大量客戶端在一時刻可能只有很少的處于就緒狀態(tài),因此隨著監(jiān)視的描述符數(shù)量的增長,其效率也會線性下降。

三、poll 服務(wù)器

#include <stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<sys/select.h>
#include<sys/poll.h>

#define _BACKLOG_ 5
#define _MAX_NUM_ 64
void usage(const char *proc)
{
	printf("Usage: %s [ip][port]\n",proc);
}
static int startup(const char *ip,const int port)
{
	int sock=socket(AF_INET,SOCK_STREAM,0);
	if(sock < 0)
	{
		perror("socket");
		exit(1);
	}
	int opt=1;
	setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	struct sockaddr_in local;
	local.sin_family=AF_INET;
	local.sin_port=htons(port);
	local.sin_addr.s_addr=inet_addr(ip);
	
	if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
	{
		perror("bind");
		exit(2);
	}	
	if(listen(sock,_BACKLOG_) < 0)
	{
		perror("listen");		
		exit(3);
	}
	return sock;
}
static int poll_server(int listen_sock)
{
	struct sockaddr_in client;
	socklen_t len=sizeof(client);
	
	struct pollfd fds[_MAX_NUM_];
	fds[0].fd=listen_sock;
	fds[0].events=POLLIN;
	fds[0].revents=0;

	size_t i=0;
	for(;i<_MAX_NUM_;++i)
	{
		fds[i].fd=-1;
		fds[i].events=0;
		fds[i].revents=0;
	}
	int max_fd=1;
	int timeout=5000;
	while(1)
	{
		switch(poll(fds,max_fd,timeout))
		{
		case -1://error
			perror("poll");
			break;
		case 0://timeout
			printf("poll timeout");
			break;
		default://normal 
			{
				for(i=0;i<_MAX_NUM_;++i)
				{
					//is listen events ready?
					if(fds[i].fd == listen_sock && fds[i].revents == POLLIN)
					{
						int accept_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
						if(accept_sock < 0)
						{
							perror("accept");
							continue;
						}
						printf("get a client...[ip: %s][port: %d]\n",\
								inet_ntoa(client.sin_addr),ntohs(client.sin_port));
						for(i=0;i<_MAX_NUM_;++i)
						{
							if(fds[i].fd == -1)
							{
								fds[i].fd=accept_sock;
								fds[i].events=POLLIN;
								max_fd++;
								break;
							}
						}
						if(i == _MAX_NUM_)
						{
							close(accept_sock);
						}
					}
					else if(fds[i].fd > 0 && fds[i].revents == POLLIN)
					{
						char buf[1024];
						ssize_t _size=read(fds[i].fd,buf,sizeof(buf)-1);
						if(_size > 0)//read success
						{
							buf[_size]='\0';
							printf("Client # %s",buf);
						}
						else if(_size == 0)//client close
						{
							printf("clint close...\n");
							struct pollfd tmp=fds[i];
							fds[i]=fds[max_fd-1];
							close(fds[max_fd-1].fd);
							fds[max_fd-1].fd=-1;
							fds[max_fd-1].events=0;
							fds[max_fd-1].revents=0;
							--max_fd;
						}

					}
					else
					{}
				}
			}
			break;
		}
	}
	return 0;
}
int main(int argc,char *argv[])
{
	if(argc != 3)
	{
		usage(argv[0]);
		return 1;
	}
	char *ip=argv[1];
	int port=atoi(argv[2]);
	int listen_sock=startup(ip,port);
	poll_server(listen_sock);
	close(listen_sock);
	return 0;
}

總結(jié):  

    poll在返回后,需要通過遍歷文件描述符來獲取已經(jīng)就緒的socket從而進行下一步操作;而且使用完監(jiān)聽套接字后,都需要進行關(guān)閉。

標(biāo)題名稱:I/O多路轉(zhuǎn)接 ---- poll
網(wǎng)站地址:http://jinyejixie.com/article20/jopdco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、企業(yè)建站域名注冊、網(wǎng)站營銷、ChatGPT、虛擬主機

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營
中江县| 温宿县| 闻喜县| 泰州市| 文登市| 霍山县| 江孜县| 英德市| 郓城县| 滨州市| 靖宇县| 长阳| 横山县| 兴业县| 蓝山县| 泰宁县| 泽州县| 辉南县| 南充市| 紫云| 丰顺县| 崇左市| 二手房| 庆阳市| 诏安县| 永定县| 华宁县| 开平市| 南郑县| 荣成市| 蓬安县| 巢湖市| 炎陵县| 丹东市| 广平县| 广汉市| 巫山县| 阿巴嘎旗| 常宁市| 玛沁县| 镇巴县|