IO模型(select epoll)

我们先从select入手写一个模型,这是经过我们优化了的

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include "wrap.h"
int main (void)
{
	int i;
	//max_fd的作用是每次在调用select时使用
	int sock_main_fd,max_fd;
	//我们自定义的文件描述符数组
	int fd_array[1024];
	//自定义文件描述符数组的指针
	int p_array;
	//监听集合,因为select中的参数是传入传出参数,所以我们需要两个,一个保存所有需要监听的文件描述符
	fd_set all_set,new_set;
	//正常创建socket的步骤
	struct sockaddr_in addr;
	sock_main_fd = Socket(AF_INET,SOCK_STREAM,0);
	bzero((void*) &addr,sizeof(addr));
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(10000);
	addr.sin_family = AF_INET;
	Bind(sock_main_fd,(struct sockaddr *)&addr,sizeof(addr));
	Listen(sock_main_fd,128);
	//初始化最大文件描述符
	max_fd = sock_main_fd;
	//进行集合的初始化
	FD_ZERO(&all_set);
	//将sock_main_fd放入集合中
	FD_SET(sock_main_fd,&all_set);
	for(i = 0;i < 1024;i++)
	{
		fd_array[i] = -1;
	}
	p_array = -1;
	while(1)
	{
		int i;
		int sock_val;
		int ready_num;
		//将集合备份传递给new_set集合
		new_set = all_set;
		ready_num = select(max_fd + 1,&new_set,NULL,NULL,NULL);
		//如果出错则退出
		if(ready_num == -1)
		{
			perr_exit("select 函数错误");
		}
		//如果为true说明有连接请求,我们进行连接
		if(FD_ISSET(sock_main_fd,&new_set))
		{
			int i;
			//accept返回值
			int link_fd;
			int port;
			char ip[100];
			struct sockaddr_in addr;
			socklen_t addr_len;
			addr_len = sizeof(addr);
			link_fd = Accept(sock_main_fd,(struct sockaddr*)&addr,&addr_len);
			//打印监听到的连接的ip地址和端口号
			inet_ntop(AF_INET,&addr.sin_addr.s_addr,ip,sizeof(ip));
			port =	ntohs(addr.sin_port);
			//打印端口号和ip地址
			printf("客户端的ip地址:%s  端口号:%d\r\n",ip,port);
			//我们将其返回的文件描述符放入到我们自定义的数组当中去
			for(i = 0;i < 1024;i++)
			{
				if(fd_array[i] == -1)
				{
					fd_array[i] = link_fd;
					break;
				}
			}
			//判断是否溢出
			if(i == 1024)
			{
				perr_exit("自定义数组有溢出的危险");
			}
			//将连接的文件描述符放入监听集合中去
			FD_SET(link_fd,& all_set);
			//判断自定义数组指针是否需要移动
			if(p_array < i)
			{
				p_array = i;
			}
			//判断当前的最大文件描述符个数
			if(link_fd > max_fd)
			{
				max_fd = link_fd;
			}
			if((ready_num -- ) == 0)
			{
				continue;
			}
		}
		//如果不是连接请求的话就是有读事件响应了
		for(i = 0; i <= p_array;i++)
		{
			if((sock_val = fd_array[i]) == -1)
			{
				continue;
			}
			if(FD_ISSET(sock_val,&new_set))		
			{
				char buf[1024];
				int n;
				//进行事件的读取操作
				if(	(n = Read(sock_val,buf,sizeof(buf))) == 0)
				{
					//清除监控集合中的值
					FD_CLR(sock_val,&all_set);
					//清除自定义数组中的值
					fd_array[i] = -1;
					//对读端进行关闭
					Close(sock_val);
				}
				else if(n > 0){
					char buf[1024];
					for(i = 0; i < n ;i++)
					{
						buf[i] = toupper(buf[i]);
					}
					//像标准输出文件描述符输出
					Write(STDOUT_FILENO,buf,n);
				}
				if((ready_num --) == 0)
				{
					continue;
				}
			}
		}
	}
	Close(sock_main_fd);
	exit(0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值