函數(shù)原型:
10年積累的成都做網(wǎng)站、成都網(wǎng)站建設、成都外貿網(wǎng)站建設經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站策劃后付款的網(wǎng)站建設流程,更有沅陵免費網(wǎng)站建設讓你可以放心的選擇與我們合作。

函數(shù)說明:該函數(shù)允許進程指示內核等待多個事件中的任何一個發(fā)生,并只在有一個或多個事件發(fā)生或經(jīng)歷一段指定的時間后才喚醒它。
參數(shù)說明:

fds:是一個struct pollfd結構類型的數(shù)組,用于存放需要檢測其狀態(tài)的Socket描述符;
每當調用這個函數(shù)之后,系統(tǒng)不會清空這個數(shù)組,操作起來比較方便;特別是對于socket連接比較多的情況下,在一定程度上可以提高處理的效率;這一點與select()函數(shù)不同,調用select()函數(shù)之后,select()函數(shù)會清空它所檢測的socket描述符集合,導致每次調用select()之前都必須把socket描述符重新加入到待檢測的集合中;因此,select()函數(shù)適合于只檢測一個socket描述符的情況,而poll()函數(shù)適合于大量socket描述符的情況;
nfds:nfds_t類型的參數(shù),用于標記數(shù)組fds中的結構體元素的總數(shù)量;
timeout:是poll函數(shù)阻塞的時間,單位:毫秒;
如果timeout==0,那么poll() 函數(shù)立即返回而不阻塞
如果timeout==INFTIM,即負數(shù),那么poll() 函數(shù)會一直阻塞下去,直到所檢測的socket描述符上的感興趣的事件發(fā)生是才返回,如果感興趣的事件永遠不發(fā)生,那么poll()就會永遠阻塞下去;
poll()函數(shù)會以輪詢方式在timeout所指定的毫秒時間長度之后返回
返回值:
>0:數(shù)組fds中準備好讀、寫或出錯狀態(tài)的那些socket描述符的總數(shù)量;
==0:數(shù)組fds中沒有任何socket描述符準備好讀、寫,或出錯;此時poll超時,超時時間是timeout毫秒
-1: poll函數(shù)調用失敗,同時會自動設置全局變量errno;
struct pollfd中event的設置參數(shù):

實現(xiàn)IO復用:關心輸入輸出條件就緒
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<poll.h>
int main()
{
struct pollfd fds[2];
fds[0].fd=0;
fds[0].events=POLLIN;
fds[0].revents=0;
fds[1].fd=1;
fds[1].events=POLLOUT;
fds[1].revents=0;
char buf[1024];
ssize_t _s;
int i=0;
int timeout=5000;
while(1)
{
timeout=5000;
switch(poll(fds,2,timeout))
{
case -1://error
perror("poll");
break;
case 0://timeout
printf("time out\n");
break;
default:
{
for(i=0;i<2;++i)
{
if(fds[i].fd==0&&fds[i].revents&POLLIN)
{
_s=read(0,buf,sizeof(buf)-1);
if(_s>0)
{
buf[_s]='\0';
if(strncmp(buf,"quit",4)==0)
{
close(fds[i].fd);
exit(0);
}
printf("echo:%s",buf);
}
//fds[i].revents=0;//not need
}
// else if(fds[i].fd==1&&fds[i].revents&&POLLOUT)
// {
// strcpy(buf,"hello");
// printf("echo: %s",buf);
// fds[i].revents=0;//not need
// }
}
}
break;
}
}
return 0;
}運行截圖:

TCP通信:監(jiān)聽socket
server:
創(chuàng)建監(jiān)聽套接字并初始化:調用socket,bind,listen,唯一描述符是監(jiān)聽描述符初始化數(shù)據(jù)結構。
阻塞于select:select等待某個事件發(fā)生或新客戶連接的建立或是數(shù)據(jù),F(xiàn)IN或RST的到達。
accept新連接
如果監(jiān)聽套接字變?yōu)榭勺x,那么已建立一個新的連接,我們調用accept并更新相應數(shù)據(jù)結構。使用fds數(shù)組中第一個未用項記錄這個已連接描述符。
檢查現(xiàn)有連接
對于每個現(xiàn)有客戶連接,我們要測試其描述符是否在select返回描述符集中,如果是就從該客戶讀取一行文本,并回顯,輸出。如果該客戶關閉了連接,那么read將返回0,更新數(shù)據(jù)結構。
poll與select不同在于描述符存儲方式不同和參數(shù)類型不同。
1.結構體數(shù)組的管理:當每次有需要關心的描述符時,將其放入結構體中,每次有無效的描述符后,將其描述符置-1,下次poll函數(shù)會忽略它。當有新的描述符加入時,從頭遍歷結構體,將為-1的元素設為要關心的描述符事件狀態(tài)。切記:當新的描述符加到結構體數(shù)組末尾時要更新關心描述符個數(shù),即poll第二個參數(shù)。
2.每次調用poll后,結構體元素revents會存儲就緒事件狀態(tài),當每次重新調用poll之前時,系統(tǒng)會自己設置其為0,重新監(jiān)聽關心事件(不需要用戶重新置0)
3.poll中參數(shù)不是輸入,輸出型,因此timeout,struct pollfd *fds參數(shù)不需重置,nfds看情況(參照第一點),而select函數(shù)是輸入輸出類型,每次調用前需重置。
//server:最終版
include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<poll.h>
#include<string.h>
#include<errno.h>
#define _BACKLOG_ 5
#define _SIZE_ 64
static void usage(const char* proc)
{
printf("%s [ip][port]\n",proc);
}
static int start(char* ip,int port)
{
//1.create a socket
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket");
exit(1);
}
//2.bind
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);
}
//3.set listen state
if(listen(sock,_BACKLOG_)<0)
{
perror("listen");
exit(3);
}
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];
//listen_sock_fd
int listen_sock=start(_ip,_port);
struct pollfd polls[_SIZE_];//struct pollfd arrays
int index=0;//effective fdnum
int timeout=5000;//millseconds
int i=0;//index
polls[0].fd=listen_sock;
polls[0].events=POLLIN;
polls[0].revents=0;
int max_num=1;
for(i=1;i<_SIZE_;++i)
{
polls[i].fd=-1;
}
char buf[1024];
ssize_t _s=0;
struct sockaddr_in remote;//accept
socklen_t len=sizeof(remote);
while(1)
{
//new start
//timeout=5000;
switch(poll(polls,max_num,timeout))
{
case 0://timeout
printf("time out...\n");
break;
case -1://error
perror("poll");
break;
default://normal
{
for(i=0;i<max_num;++i)
{
if(polls[i].fd==listen_sock&&(polls[i].revents&\
POLLIN))
{
printf("get a connect\n");
int new_sock=accept(listen_sock,\
(struct sockaddr*)&remote,&len);
if(new_sock<0)
{
perror("accept");
continue;
}
int j=1;//0 is listensock
for(;j<_SIZE_;++j)
{
if(polls[j].fd==-1)
{
polls[j].fd=new_sock;
polls[j].events=POLLIN;
polls[j].revents=0;
break;
}
}
if(j==_SIZE_)
{
printf("full");
close(new_sock);
return -1;
}
if(j==max_num)//加入的是max_num為下標的位置,即最后
max_num+=1;
}
else if(polls[i].fd>0&&(polls[i].revents&\
POLLIN))//read ready
{
_s=read(polls[i].fd,buf,sizeof(buf)-1);
if(_s>0)
{
buf[_s]='\0';
printf("client: %s",buf);
write(polls[i].fd,buf,strlen(buf));
polls[i].revents=0;//not need
}
else if(_s==0)//client close
{
close(polls[i].fd);
polls[i].fd=-1;
printf("client is close\n");
}
}
else
{}
}
}
break;
}
}
for(i=0;i<_SIZE_;++i)
{
if(polls[i].fd!=-1)
close(polls[i].fd);
}
return 0;
}
//server:優(yōu)質版
#include<stdio.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<poll.h>
#include<string.h>
#include<errno.h>
#define _BACKLOG_ 5
#define _SIZE_ 64
static void usage(const char* proc)
{
printf("%s [ip][port]\n",proc);
}
static int start(char* ip,int port)
{
//1.create a socket
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket");
exit(1);
}
//2.bind
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);
}
//3.set listen state
if(listen(sock,_BACKLOG_)<0)
{
perror("listen");
exit(3);
}
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];
//listen_sock_fd
int listen_sock=start(_ip,_port);
struct pollfd polls[_SIZE_];//struct pollfd arrays
int index=0;//effective fdnum
int timeout=5000;//millseconds
int i=0;//index
polls[0].fd=listen_sock;
polls[0].events=POLLIN;
polls[0].revents=0;
++index;
for(i=1;i<_SIZE_;++i)
{
polls[i].fd=-1;
}
char buf[1024];
ssize_t _s=0;
struct sockaddr_in remote;//accept
socklen_t len=sizeof(remote);
while(1)
{
//new start
timeout=5000;
int j=index;
i=0;
//消除struct pollfd中已不關心的描述符:前移,得到有效的最后一個元素下標
while(i<j)
{
while(i<j&&polls[i].fd!=-1)//從前面數(shù)第一個無效的
++i;
while(i<j&&polls[j].fd==-1)//從后面數(shù)第一個有效的
--j;
if(i<j)//復制fd
{
polls[i].fd=polls[j].fd;
polls[i].events=POLLIN;//可不需要,因為event參數(shù)不發(fā)生變化,本程序只監(jiān)聽讀事件
polls[index].revents=0;
}
}
index=i;
//printf("%d",index);
//須保證polls是有序的
switch(poll(polls,index,timeout))//index表明最后一個關心的描述符在數(shù)組中下標+1=個數(shù)
{
case 0://timeout
printf("time out...\n");
break;
case -1://error
perror("poll");
break;
default://normal
{
for(i=0;i<index;++i)
{
if(polls[i].fd==listen_sock&&(polls[i].revents&\
POLLIN))
{
printf("get a connect\n");
int new_sock=accept(listen_sock,\
(struct sockaddr*)&remote,&len);
if(new_sock<0)
{
perror("accept");
continue;
}
if(index==_SIZE_)
{
printf("full");
close(new_sock);
return -1;
}
polls[index].fd=new_sock;
polls[index].events=POLLIN;
polls[index].revents=0;
++index;
}
else if(polls[i].fd>0&&(polls[i].revents&\
POLLIN))//read ready
{
_s=read(polls[i].fd,buf,sizeof(buf)-1);
if(_s>0)
{
buf[_s]='\0';
printf("client: %s",buf);
write(polls[i].fd,buf,strlen(buf));
polls[i].revents=0;
}
else if(_s==0)//client close
{
close(polls[i].fd);
polls[i].fd=-1;
printf("client is close\n");
}
}
else
{}
}
}
break;
}
}
for(i=0;i<_SIZE_;++i)
{
if(polls[i].fd!=-1)
close(polls[i].fd);
}
return 0;
}
//仿select版,用輔助數(shù)組存儲,沒有利用poll結構體的優(yōu)點,event不清空,開銷大
int main(int argc,char* argv[])
{
if(argc!=3)
{
usage(argv[0]);
return 1;
}
int _port=atoi(argv[2]);
char* _ip=argv[1];
//listen_sock_fd
int listen_sock=start(_ip,_port);
struct pollfd polls[_SIZE_];//struct pollfd arrays
int index=0;//effective fdnum
int timeout=5000;//millseconds
int i=0;//index
int fds[_SIZE_];
fds[0]=listen_sock;
for(i=1;i<_SIZE_;++i)
{
fds[i]=-1;
}
char buf[1024];
ssize_t _s=0;
struct sockaddr_in remote;//accept
socklen_t len=sizeof(remote);
while(1)
{
index=0;//new start
timeout=5000;
for(i=0;i<_SIZE_;++i)
{
polls[i].fd=-1;
}
for(i=0;i<_SIZE_;++i)
{
if(fds[i]!=-1)
{
polls[index].fd=fds[i];
polls[index].events=POLLIN;
polls[index].revents=0;
++index;
}
}
switch(poll(polls,index,timeout))
{
case 0://timeout
printf("time out...\n");
break;
case -1://error
perror("poll");
break;
default://normal
{
for(i=0;i<index;++i)
{
if(polls[i].fd==listen_sock&&(polls[i].revents&\
POLLIN))
{
printf("get a connect\n");
int new_sock=accept(listen_sock,\
(struct sockaddr*)&remote,&len);
if(new_sock<0)
{
perror("accept");
continue;
}
int j;
for(j=0;j<_SIZE_;++j)
{
if(fds[j]==-1)
{
fds[j]=new_sock;
break;
}
}
if(j==_SIZE_)
{
printf("full");
close(new_sock);
return -1;
}
polls[i].revents=0;//reset
}
else if(polls[i].fd>0&&(polls[i].revents&\
POLLIN))//read ready
{
_s=read(polls[i].fd,buf,sizeof(buf)-1);
if(_s>0)
{
buf[_s]='\0';
printf("client: %s",buf);
write(polls[i].fd,buf,strlen(buf));
}
else if(_s==0)//client close
{
close(polls[i].fd);
int j;
for(j=0;j<_SIZE_;++j)
{
if(fds[j]==polls[i].fd)
{
fds[j]=-1;
break;
}
}
printf("client is close\n");
}
}
else
{}
}
}
break;
}
}
for(i=0;i<_SIZE_;++i)
{
if(fds[i]!=-1)
close(fds[i]);
}
return 0;
}
//client:
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
void Usage(const char* proc)
{
printf("%s [ip][port]",proc);
}
int main(int argc,char* argv[])
{
if(argc!=3)
{
Usage(argv[0]);
return 1;
}
int client_sock=socket(AF_INET,SOCK_STREAM,0);
if(client_sock<0)
{
perror("socket");
return 1;
}
struct sockaddr_in client;
client.sin_family=AF_INET;
client.sin_port=htons(atoi(argv[2]));
client.sin_addr.s_addr=inet_addr(argv[1]);
char buf[1024];
ssize_t _s;
if(connect(client_sock,(struct sockaddr*)&client,sizeof(client))<0)
{
perror("connection");
return 2;
}
while(1)
{
printf("please enter:\n");
_s=read(0,buf,sizeof(buf)-1);
if(_s>0)
buf[_s]='\0';
if(strncmp(buf,"quit",4)==0)
{
printf("client is quit\n");
break;
}
write(client_sock,buf,_s);
_s=read(client_sock,buf,sizeof(buf)-1);
if(_s>0)
{
buf[_s]='\0';
printf("server->client: %s",buf);
}
}
close(client_sock);
return 0;
}運行截圖:

網(wǎng)站題目:poll實現(xiàn)IO復用,TCP通信
轉載來源:http://chinadenli.net/article10/gdsego.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊、網(wǎng)站設計公司、網(wǎng)站營銷、品牌網(wǎng)站制作、網(wǎng)站制作、手機網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)