文章目录
由于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;
}