引言
上一篇笔记介绍了多种TCP服务器处理多套接字的方法,本篇笔记主要内容是记录实现TCP服务器多路复用的POLL函数的使用方法。
实现思想
poll函数的原理
- 假设服务器中有三个不同的套接字负责不同的任务
- 为每个套接字建立独有的pollfd结构体
- 并且在结构体中拥有events存放结构体负责的事件:读事件,写事件,报错事件等
- 将以上的所有结构体组成一个结构体数组作为poll函数的参数以供使用
有数据来临的操作原理:
- 当有连接请求,数据同时到达,会分配到相对应的Pollfd结构体中
- socketfd收到连接请求后,系统会在revents自动生成连接就绪
- connfd2收到数据后,系统会在revents自动生成读就绪
- 此时,Poll函数会自动返回2
代码实现
server.c:
#include "head4sock.h"
int main(int argc, char **argv)
{
int sockfd = Socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in srvaddr;
socklen_t len =sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = PF_INET;
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
srvaddr.sin_port = htons(atoi(argv[1]));
Bind(sockfd,(struct sockaddr *)&srvaddr,len);
Listen(sockfd,3);
int connfd = Accept(sockfd,NULL,NULL);
//struct pollfd *fds = calloc(n,sizeof(struct pollfd));
//当不知道需要监听多少个描述符的时候,定义为指针
struct pollfd fds[2]; //监听两个描述符
fds[0].fd = STDIN_FILENO;
fds[0].events =POLLRDNORM | POLLERR; //只关心fd套接字上的读操作 和错误操作
fds[1].fd = connfd;
fds[1].events =POLLRDNORM | POLLERR;
char buf[SIZE];
while (1)
{
poll(fds,2,0);
bzero(buf,SIZE);
if (fds[0].revents & POLLRDNORM) //如果条件成立,则有数据输入
{
fgets(buf,SIZE,stdin);
write(connfd,buf,strlen(buf));
}
if (fds[0].revents & POLLERR) //如果条件成立,则发生错误
{
perror("stdin error");
break;
}
if (fds[1].revents & POLLRDNORM) //如果条件成立,则有数据输入
{
if(Read(connfd,buf,SIZE) ==0)
break;
printf("form peer:%s\n", buf);
}
if (fds[1].revents & POLLERR) //如果条件成立,则发生错误
{
perror("read() failed");
break;
}
}
}
client.c:
#include "head4sock.h"
int main(int argc, char **argv)
{
int sockfd = Socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in srvaddr;
socklen_t len =sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = PF_INET;
inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);
srvaddr.sin_port = htons(atoi(argv[2]));
Connect(sockfd,(struct sockaddr *)&srvaddr,len);
//struct pollfd *fds = calloc(n,sizeof(struct pollfd));
//当不知道需要监听多少个描述符的时候,定义为指针
struct pollfd fds[2]; //监听两个描述符
fds[0].fd = STDIN_FILENO;
fds[0].events =POLLRDNORM | POLLERR; //只关心fd套接字上的读操作 和错误操作
fds[1].fd = sockfd;
fds[1].events =POLLRDNORM | POLLERR;
char buf[SIZE];
while (1)
{
poll(fds,2,0);
bzero(buf,SIZE);
if (fds[0].revents & POLLRDNORM) //如果条件成立,则有数据输入
{
fgets(buf,SIZE,stdin);
write(sockfd,buf,strlen(buf));
}
if (fds[0].revents & POLLERR) //如果条件成立,则发生错误
{
perror("stdin error");
break;
}
if (fds[1].revents & POLLRDNORM) //如果条件成立,则有数据输入
{
if(Read(sockfd,buf,SIZE) ==0)
break;
printf("form peer:%s\n", buf);
}
if (fds[1].revents & POLLERR) //如果条件成立,则发生错误
{
perror("read() failed");
break;
}
}
return 0;
}