select是什么:是一种轮询方式(遍历)实现的IO多路复用
IO多路复用是什么:让输入/输出设备能多次使用(复用),现在因为有 阻塞(accept、recv等函数造成) 所以不能多次使用
- select 适用于小数量级 是阻塞的
- poll 很少用
- epoll 适用于大数量级 事件(通知)的方式实现
IO操作(accept、recv)前,先判断是否有动静(有数据可读、可写)若有,再执行io操作,没有则不执行
IO多路复用监视的是文件描述符号
fd_set 文件描述集合,类似数组
#include <sys/select.h>
int select(
int nfds, //文件描述符号限制,一般是最大描述符号+1
fd_set *readfds, //输入描述符号集合
fd_set *writefds, //output fds
fd_set *exceptfds, //erroroutput fds
struct timeval *timeout //延时
);
void FD_CLR(int fd, fd_set *set); //把fd从fds中删除
int FD_ISSET(int fd, fd_set *set); //查找描述符号
void FD_SET(int fd, fd_set *set); //把fd放入fds中
void FD_ZERO(fd_set *set); //清空描述符号集
select编程模型:
1.创建描述符号集
2.放入要监视的描述符号
3.监视(阻塞式)
4.根据监视返回的值进行对应事件处理
5.循环2-4
void _select()
{
fd_set fds;
fd_set fdsOut;
// FD_ZERO(&fds);
FD_ZERO(&fdsOut);
// FD_SET(0,&fds);
FD_SET(1, &fdsOut);
int r;
char buff[1024];
while (1)
{
FD_ZERO(&fds);
FD_SET(0, &fds);
r = select(2, &fds, &fdsOut, NULL, NULL);
if (r > 0)
{
if (FD_ISSET(0, &fds))
{
printf("是0有动静\n");
scanf("%s", buff);
}
if (FD_ISSET(1, &fdsOut))
{
printf("是1有动静\n");
FD_CLR(1, &fdsOut);
FD_ZERO(&fdsOut);
}
printf("r:%d\n", r);
}
else if (0 == r)
{
printf("没有动静\n");
}
else
{
printf("错误:%m\n");
}
// 处理完之后要清除
// FD_CLR(0,&fds);
// 再重新放回去
// FD_SET(0,&fds);
}
}