内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

socket編程中poll怎么使用

這篇文章主要介紹“socket編程中poll怎么使用”,在日常操作中,相信很多人在socket編程中poll怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”socket編程中poll怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),中山企業(yè)網(wǎng)站建設(shè),中山品牌網(wǎng)站建設(shè),網(wǎng)站定制,中山網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,中山網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。

一. 關(guān)于poll

    對于IO復(fù)用模型,其優(yōu)點無疑是免去了對一個個IO事件就緒的等待,轉(zhuǎn)而代之的是同時對多個IO數(shù)據(jù)的檢測,當(dāng)檢測等待的事件中至少有一個就緒的時候,就會返回告訴用戶進程“已經(jīng)有數(shù)據(jù)準備好了,快看看是哪個趕緊處理”,而對于IO復(fù)用的實現(xiàn),除了可以用select函數(shù),另外一個函數(shù)仍然支持這種復(fù)用IO模型,就是poll函數(shù);


二. poll函數(shù)的用法

    雖然同樣是對多個IO事件進行檢測等待,但poll和select多少還是有些不同的:

socket編程中poll怎么使用

函數(shù)參數(shù)中,

先來說nfds,這個是指當(dāng)前需要關(guān)心的文件描述符的個數(shù);

timeout同樣是設(shè)置超時時間,只是和select的timeout是一個結(jié)構(gòu)體不一樣,這里只是一個整型類型,且含義是毫秒;

fds是一個結(jié)構(gòu)體指針,如下:

socket編程中poll怎么使用

結(jié)構(gòu)體中,

fd表示所要關(guān)心的文件描述符;

events表示該文件描述符所關(guān)心的事件,這是一個輸入型參數(shù),要告訴操作系統(tǒng)這個文件描述符對應(yīng)的事件所關(guān)心的操作事件是什么,比如讀或?qū)懀?/p>

revents是一個輸出型參數(shù),表示當(dāng)poll返回時告訴用戶什么操作事件是就緒的,比如如果POLLIN是就緒的,那么返回時revent的值就是POLLIN,告訴用戶fd事件的POLLIN是就緒的;

events和revents的值可以為如下:

socket編程中poll怎么使用

選項其實不止這三個,只是這里的討論中這三個選項是最常用的;

events設(shè)置為POLLIN表示fd所需要讀取數(shù)據(jù),而revents若返回POLLIN則表示data已經(jīng)ready可以讀取了;

同樣,events設(shè)置為POLLOUT表示fd所關(guān)心數(shù)據(jù)的寫入,而revents返回POLLOUT則表示寫事件就緒可以進行數(shù)據(jù)的寫入;

至于POLLPRI,后面的解釋是作為緊急選項來設(shè)置的,在TCP協(xié)議報文中有個URG的緊急指針是表示先從緊急數(shù)據(jù)的地方開始讀取,這里也是這個意思;

與select不同的是,reads與writes是輸入輸出參數(shù),我上一篇博客中設(shè)置中:

 else if(fds[i] > 0 &&\
                                FD_ISSET(fds[i],&reads))    //正常事件,但是是非監(jiān)聽時間,也就代表時新建立的new_sock。
                                {
                                //  char buf[1024];
                                    ssize_t s = read(fds[i],buf,sizeof(buf) -1);
                                    if(s > 0)
                                    {
                                        buf[s] = '\0';
                                    //  printf("client : %s\n",buf);
                                        printf("client : %s",buf);
                                        FD_SET(fds[i],&writes);
                                    //  write(fds[i],buf,sizeof(s)+1);
                                    }
                                    else if(s == 0)
                                    {
                                        printf("client quit...\n");
                                        close(fds[i]);
                                        fds[i] = -1;
                                    }
                                    else{}
                                }
                        else{}
 
                        if(fds[i] > 0&&\
                                FD_ISSET(fds[i],&writes))
                        {
                            write(fds[i],buf,sizeof(buf));
                        }

在獲取讀事件時對將fds[i],設(shè)置到寫事件中,而在poll中,讀事件判斷中修改設(shè)置為寫事件。需要等待下一次循環(huán),才能夠獲取到寫事件,然后還必須將events屬性在設(shè)置回來。

poll與select不同在于描述符存儲方式不同和參數(shù)類型不同。

1.結(jié)構(gòu)體數(shù)組的管理:當(dāng)每次有需要關(guān)心的描述符時,將其放入結(jié)構(gòu)體中,每次有無效的描述符后,將其描述符置-1,下次poll函數(shù)會忽略它。當(dāng)有新的描述符加入時,從頭遍歷結(jié)構(gòu)體,將為-1的元素設(shè)為要關(guān)心的描述符事件狀態(tài)。切記:當(dāng)新的描述符加到結(jié)構(gòu)體數(shù)組末尾時要更新關(guān)心描述符個數(shù),即poll第二個參數(shù)。

2.每次調(diào)用poll后,結(jié)構(gòu)體元素revents會存儲就緒事件狀態(tài),當(dāng)每次重新調(diào)用poll之前時,系統(tǒng)會自己設(shè)置其為0,重新監(jiān)聽關(guān)心事件(不需要用戶重新置0)

3.poll中參數(shù)不是輸入,輸出型,因此timeout,struct pollfd *fds參數(shù)不需重置,nfds看情況(參照第一點),而select函數(shù)是輸入輸出類型,每次調(diào)用前需重置。

下面看服務(wù)端的代碼,客戶端就不寫了:

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

#define _BACKLOG_ 5
#define _SIZE_ 64

static void usage (const char *proc)
{
	printf("%s [ip][prot]\n",proc);
}
 
static int start(char *ip,int port)	
{
	int sock = socket(AF_INET,SOCK_STREAM,0);
	if(sock < 0)
	{
		perror("socket");
		exit(1);
	}
	
	int opt = 1;
	if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)) < 0)
	{
		perror("setsockopt");
		exit(3);
	}

	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(2);
	}
	return sock;
}



int main(int argc,char* argv[])
{
	if(argc != 3)
	{
		usage(argv[0]);
		return 1;
	}

	int port = atoi(argv[2]);
	char *ip = argv[1];

	int listen_sock = start(ip,port);

	//pollfd arrays
	struct pollfd polls[_SIZE_];
	int index = 0;
	int timeout = 5000; //check question time
	int i = 0;
	polls[0].fd = listen_sock;
	polls[0].events = POLLIN;
	polls[0].revents = 0;
	++index;
	//init polls.fd
	for(i = 1;i < _SIZE_;++i)
	{
		polls[i].fd = -1;
	}
	char buf [1024];
	ssize_t s = 0;
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int done = 0;
	int max_fd = 1;
	while(!done)
	{
		switch(poll(polls,max_fd,timeout))
		{
			case -1:
				perror("poll");
				break;
			case 0:
				printf("timeout\n");
				break;
			default:
				{
					size_t i = 0;
					for(;i<_SIZE_;++i)
					{
						if((polls[i].fd == listen_sock) && (polls[i].revents == POLLIN))
						{
							int accept_sock = accept(listen_sock,(struct sockaddr*)&client,&len);
							if(accept_sock < 0)
							{
								perror("accept");
								continue;
							}
							printf("connet success\n");
							for(;i < _SIZE_;++i)
							{
								if(polls[i].fd == -1)
								{
									polls[i].fd = accept_sock;
									polls[i].events = POLLIN;
									++max_fd;
									break;
								}
							}
							if(i == _SIZE_)
							{
								close(accept_sock);
							}
						}
						else if((polls[i].fd > 0) &&(polls[i].revents == POLLIN) )
						{
							ssize_t size = read(polls[i].fd,buf,sizeof(buf)-1);
							if(size < 0)
							{
								perror("read");
								continue;
							}
							else if(size == 0)
							{
								printf("client close \n");
								struct pollfd tmp = polls[i];
								polls[i] = polls[max_fd -1];
								polls[max_fd -1] = tmp;

								close(polls[max_fd - 1].fd);
								polls[max_fd - 1].fd = -1;
							}
							else
							{
								buf[size] = '\0';
								printf("client # %s",buf);
								polls[i].events = POLLOUT;
							}
						}
						else if(polls[i].fd > 0&& \
								polls[i].revents == POLLOUT)
						{
							write(polls[i].fd,buf,sizeof(buf));
							polls[i].events = POLLIN;
						}
					}
				}
				break;
		}
	}
	return 0;
}

運行結(jié)果:

socket編程中poll怎么使用

到此,關(guān)于“socket編程中poll怎么使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

當(dāng)前名稱:socket編程中poll怎么使用
分享路徑:http://www.rwnh.cn/article48/jsdeep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作虛擬主機、企業(yè)建站、手機網(wǎng)站建設(shè)、微信小程序網(wǎng)站排名

廣告

聲明:本網(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)

搜索引擎優(yōu)化
鲜城| 宣威市| 司法| 大城县| 龙井市| 泰宁县| 莱西市| 阜南县| 泽库县| 什邡市| 永济市| 镇平县| 崇州市| 衡东县| 高安市| 垫江县| 石林| 温宿县| 巴林右旗| 沈阳市| 洪湖市| 称多县| 开原市| 疏勒县| 兴文县| 万安县| 资兴市| 贵定县| 科技| 赤城县| 涞源县| 内江市| 前郭尔| 栾城县| 浦江县| 伊宁县| 沁源县| 深泽县| 嘉峪关市| 崇义县| 汤阴县|