多路复用技术Linux下poll模型代码实现
#include "wrap.h"
#include <poll.h>
#include <ctype.h>
#include <fcntl.h>
//委托监控最大值
#define MAXPFD 1024
int main()
{
//变量定义
int lfd, cfd, nready, maxi, n, i, sockfd, flags;
char buf[1024];
fd_set readfds, tempfds;
struct pollfd client[MAXPFD];
//创建SOCKET、设置端口复用、绑定端口、监听
lfd = tcp4BindListen(9791, NULL, 128);
//委托监控监听文件描述符的读事件
maxi = 0;
client[0].fd = lfd;
client[0].events = POLLIN;
//将还未委托的文件描述符初始化为-1
for(i = 1; i < 1024; i++)
{
client[i].fd = -1;
}
while(1)
{
nready = poll(client, maxi + 1, -1);
if(nready < 0)
{
if(errno == EINTR)//被信号中断
{
continue;
}
break;
}
//有客户端请求连接
if(client[0].revents == POLLIN)
{
cfd = Accept(lfd, NULL, NULL);
//选择一个数组下标最小且未被使用的结构体存放通信文件描述符
for(i = 1; i < MAXPFD; i++)
{
if(client[i].fd == -1)
{
//委托监控读事件
client[i].fd = cfd;
client[i].events = POLLIN;
//设置通信文件描述符为非阻塞
flags = fcntl(cfd, F_GETFL, 0);
flags = flags | O_NONBLOCK;
fcntl(cfd, F_SETFL, flags);
break;
}
}
//如果数组最大坐标已被占用,拒绝连接请求
if(i == MAXPFD)
{
close(cfd);
printf("拒绝连接请求\n");
}
else
{
printf("连接成功\n");
if(maxi < i)
{
maxi = i;
}
}
//如果可读事件-1为0,跳出当前循环
if(--nready == 0)
{
continue;
}
}
//有客户端发送数据
for(i = 1; i <= maxi; i++)
{
//client数组中fd已关闭
if(client[i].fd == -1)
{
continue;
}
sockfd = client[i].fd;
if(client[i].revents == POLLIN)
{
while(1)
{
bzero(buf, sizeof(buf));
n = Read(sockfd, buf, sizeof(buf));
//如果客户断开连接
if(n == 0)
{
printf("客户断开连接\n");
close(sockfd);
client[i].fd = -1;
if(client[i].fd == maxi)
{
maxi -= 1;
}
break;
}
//如果数据读取完毕
else if(n < 0)
{
printf("数据接受完毕\n");
break;
}
//如果还有可读数据
else
{
printf("读取数据 %s", buf);
/*
核心操作
*/
}
//如果可读事件-1为0,跳出for循环
if(--nready == 0)
{
break;
}
}
}
}
}
//关闭通信文件描述符
close(lfd);
return 0;
}
~ ```