io的多路复用,当客户端的并发需求并不是很高时,服务端就没有必要来使用多进程或者多线程来实现高并发。可以使用io复用的技术来进行一般的并发处理,
这种技术的优点是节约资源,但当客户端都是高并发时则不能去使用该模型。
步骤:
1.定义集合 fd_set rd_set,rw_set;
2.把集合内清0 void FD_ZERO(fd_set *set);
3.将指定的fd描述符添加到set集合中 void FD_SET(int fd, fd_set *set);
4.int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
功能:完成指定描述符集合中有效描述符的动态检测。
该函数具有阻塞等待功能,在函数执行完毕后
目标测试集合中将只保留最后有数据的描述符。
参数:nfds 描述符的上限值,一般是链接后描述符的最大值+1;
readfds 只读描述符集
writefds 只写描述符集
exceptfds 异常描述符集
以上三个参数都是 fd_set * 的描述符集合类型
timeout 检测超时 如果是NULL表示一直检测不超时 。
5.int FD_ISSET(int fd, fd_set *set);
功能:判断值为fd的描述符是否在set集合中,
如果在则返回真,否则返回假。
6.还有一个函数,但一般不太用
void FD_CLR(int fd, fd_set *set);
功能:将指定的set集合中编号为fd的描述符号删除。
基于io复用两人聊天
分析:设定一个文件描述符集合在系统中,将集合清空,向集合中写入要使用到的文件描述符。用select函数把集合初始化下,告诉系统集合里面都存在什么文件描述符,
集合中的文件描述符就相当与触发条件,由函数FD_ISSET()来判断,当其中一个文件描述符被触发时函数会判断,
并进入到相应的if判断语句中去。当一次触发执行完后,程序又会等到select函数的地方等待,当相应的文件描述符被触发时,
系统就会引导程序进入相应的if函数中。
a方
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int ret1 = mkfifo("fifo1", 0666);
int ret2 = mkfifo("fifo2", 0666);
if(-1 == ret1 || -1 == ret2)
{
if(errno !=EEXIST)
{
perror("mkfifo_error");
exit(1);
}
}
int fd = open("fifo1" ,O_RDONLY);
if(-1 == fd)
{
perror("fd");
exit(1);
}
int fd1 = open("fifo2" ,O_WRONLY);
if(-1 == fd1)
{
perror("fd1");
exit(1);
}
fd_set rd_set, rw_set;
FD_ZERO(&rd_set);
FD_ZERO(&rw_set);
FD_SET(fd, &rd_set);
FD_SET(0, &rd_set);
printf("this a chatroom\n");
while(1)
{
rw_set = rd_set;
if(fd > fd1)
{
select(fd,&rw_set,NULL,NULL,NULL);
}
else
{
select(fd+1,&rw_set,NULL,NULL,NULL);
}
if(FD_ISSET(fd,&rw_set))
{
char buf[512]= {0};
int ret = read(fd, buf,512);
if(ret <= 0)
{
return 0;
}
if(0 == strcmp(buf,"quit\n"))
{
remove("fifo1");
remove("fifo2");
return 0;
}
printf("b----->a %s", buf);
}
if(FD_ISSET(0,&rw_set))
{
char buf[512] = {0};
fgets(buf,512,stdin);
write(fd1,buf,512);
if(0 == strcmp(buf,"quit\n"))
{
return 0;
}
}
}
return 0;
}
b方
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
int ret1 = mkfifo("fifo1", 0666);
int ret2 = mkfifo("fifo2", 0666);
if(-1 == ret1 || -1 == ret2)
{
if(errno !=EEXIST)
{
perror("mkfifo_error");
exit(1);
}
}
int fd = open("fifo1" ,O_WRONLY);
if(-1 == fd)
{
perror("fd");
exit(1);
}
int fd1 = open("fifo2" ,O_RDONLY);
if(-1 == fd1)
{
perror("fd1");
exit(1);
}
fd_set rd_set, rw_set;
FD_ZERO(&rd_set);
FD_ZERO(&rw_set);
FD_SET(fd1, &rd_set);
FD_SET(0, &rd_set);
printf("this b chatroom\n");
while(1)
{
rw_set = rd_set;
if(fd > fd1)
{
select(fd+1,&rw_set,NULL,NULL,NULL);
}
else
{
select(fd1+1,&rw_set,NULL,NULL,NULL);
}
if(FD_ISSET(fd1,&rw_set))
{
char buf[512]= {0};
int ret = read(fd1, buf,512);
if(ret <=0)
{
return 0;
}
if(0 == strcmp(buf,"quit\n"))
{
close(fd);
close(fd1);
remove("fifo1");
remove("fifo2");
return 0;
}
printf("a----->b %s", buf);
}
if(FD_ISSET(0,&rw_set))
{
char buf[512] = {0};
fgets(buf,512,stdin);
write(fd,buf,512);
if(0 == strcmp(buf,"quit\n"))
{
return 0;
}
}
}
return 0;
}