Day 44 初识IO复用

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值