一、poll结构体
struct pollfd
{
int fd;//文件描述符
short events; //等待的事件
short revents;//实际发生的事件 - 内核给的反馈
};
二、poll函数
int poll(struct pollfd *fd,nfds_t nfds,int timeout);
/*
pollfd -- 数组的地址
nfds:数组的最大长度,数组中最后一个使用的元素下标+1
内核会轮询检测fd数组中每个文件描述符
timeout:
-1:永久阻塞
0:调用完成立即返回
>0:等待的时长:毫秒
返回值:IO发送变化的文件描述符的个数
*/
二、poll代码实现
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <poll.h>
#define SERV_PORT 8989
int main(int argc,const char* argv[])
{
int lfd,cfd;
if(argc<2)
{
printf("eg: ./a.out port\n");
exit(1);
}
struct sockaddr_in serv_addr;
socklen_t serv_len,client_len;
//创建套接字
lfd=socket(AF_INET,SOCK_STREAM,0);
//初始化服务器sockaddr_in
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;//地址族
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);//监听本机所有IP
serv_addr.sin_port=htonl(SERV_PORT);//设置端口
serv_len=sizeof(serv_len);
//绑定IP和端口
bind(lfd,(struct sockaddr*)&serv_addr,serv_len);
//设置同时监听的最大个数
listen(lfd,36);
printf("Start accept.....\n");
struct sockaddr_in client_addr;
socklen_t cli_len=sizeof(client_addr);
struct pollfd allfd[1024];
int max_index=0;
//init
for(int i=0;i<1024;++i)
{
allfd[i].fd=-1;
allfd[i].events=POLLIN;
}
allfd[0].fd=lfd;
allfd[0].events=POLLIN;
while(1)
{
int i=0;
int ret=poll(allfd,max_index+1,-1);
if(ret==-1)
{
perror("select error");
exit(1);
}
//客户端发起了新连接
if(allfd[0].revents & POLLIN)
{
client_len=sizeof(client_addr);
//接受连接请求 - accept 不阻塞
int cfd=accept(lfd,(struct sockaddr*)&client_addr,&client_len);
printf("=================\n");
for(i=0;i<1024;++i)
{
if(allfd[i].fd==-1)
{
allfd[i].fd=cfd;
break;
}
}
max_index=max_index<i?i:max_index;
}
//遍历数组
for(i=1;i<max_index+1;++i)
{
int fd=allfd[i].fd;
if(fd==-1)
continue;
if(allfd[i].revents&POLLIN)
{
// 接受数据
char buf[1024]={0};
int len=recv(i,buf,sizeof(buf),0);
if(len==-1)
{
perror("recv error");
exit(1);
}
else if(len==0)
{
printf("客户端已经断开了连接\n");
close(i);
allfd[i].fd=-1;
}
else
{
printf("recv buf:%s\n",buf);
send(fd,buf,strlen(buf)+1,0);
}
}
}
}
close(lfd);
return 0;
}