IO的多路复用


使用select函数实现io多路复用
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

1、select()
int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);

   nfds:最大的文件描述符加1
readfds:读文件描述符集合
writefds:写文件描述符集合
exceptfds:其他或者异常的
timeout:超时检测
     NULL  阻塞         成功:准备就绪的文件描述符的个数   失败:-1

2、相关的宏函数:

void FD_ZERO(fd_set *set);
清空一个集合set
void FD_SET(int fd, fd_set *set);
将文件描述符fd添加到集合set里面
void FD_CLR(int fd, fd_set *set);
将文件描述符fd从集合set里面移除
int  FD_ISSET(int fd, fd_set *set);
判断文件描述符fd是否在集合里面
0  不存在
1  存在

3、实现的步骤举例;

第一步:
创建一个集合并清空集合
fd_set readfds(这是一个定义好的文件描述符列表的结构体)
int maxfd

FD_ZERO(&readfds);
maxfd = sockfd;

第二步:将需要执行io操作的文件描述符添加到集合里面       ( 用while(1)循环包含第二步到第四步,可多次实现复用)

FD_SET(0, &readfds);
FD_SET(sockfd, &readfds);

第三步:调用函数,阻塞等待文件描述符准备就绪
(注:当select函数返回之后,会从集合里面移除除当前准备就绪的文件描述符以外其他所有的)
select(maxfd + 1, &readfds, NULL, NULL, NULL)

第四步:判断当前集合里面还有哪个文件描述符,则直接执行相应操作即可

if(FD_ISSET(0, &readfds) == 1)
{
fgets(buf, N, stdin);
buf[strlen(buf) - 1] = '\0';

printf("buf = %s\n", buf);
}

if(FD_ISSET(sockfd, &readfds) == 1)
{
if((acceptfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen)) < 0)
{
ERRLOG("fail to accept");
}

printf("%s -- %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}

猜你喜欢

转载自blog.csdn.net/weixin_42155195/article/details/81008106