当前位置: 首页 > news >正文

高并发服务器-多路IO转接-select

多路IO转接select

概述

多路IO转接服务器也叫做多任务IO服务器。该类服务器实现的主旨思想是,不再由应用程序自己监视客户端连接,取而代之由内核替应用程序监视文件。

文章目录

    • 多路IO转接select
    • 概述
    • select
    • 相关函数
    • 辅助函数
    • select 优缺点
    • 练习

select

  1. select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数并不能改变select监听文件个数

  2. 解决1024以下客户端时使用select是很合适的,但如果链接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率,不应在select上投入更多精力。

相关函数

#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);nfds: 		监控的文件描述符集里最大文件描述符加1readfds:	监控有读数据到达文件描述符集合,传入传出参数writefds:	监控写数据到达文件描述符集合,传入传出参数  NULLexceptfds:	监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数 NULLtimeout:	定时阻塞监控时间,3种情况   //超时处理。1.NULL,永远等下去2.设置timeval, > 0 等待固定时间3.设置timeval里时间均为0,检查描述字后立即返回,轮询struct timeval {long tv_sec; /* seconds */long tv_usec; /* microseconds */};void FD_CLR(int fd, fd_set *set); 	//把文件描述符集合里fd位清0int FD_ISSET(int fd, fd_set *set); 	//测试文件描述符集合里fd是否置1void FD_SET(int fd, fd_set *set); 	//把文件描述符集合里fd位置1void FD_ZERO(fd_set *set); 			//把文件描述符集合里所有位清0

辅助函数

fd_set set;
// 清空
void FD_ZERO(fd_set *set);
// 将 fd 从 set集合中清除出去。
void FD_CLR(int fd, fd_set *set);
// 将 fd 添加到监听结合 set中
void FD_SET(int fd, fd_set *set);
// 判断 fd 是否在集合set中
int  FD_ISSET(int fd, fd_set *set);返回:在:1. 不在:0// 举例:
fd_set rset;		// 创建 read事件监听集合
FD_ZERO(&rset);		// 清空 读集合
FD_SET(lfd, &rset);	// 将 lfd 添加到读集合
FD_SET(cfd1, &rset);	// 将 cfd1 添加到读集合
FD_SET(cfd3, &rset);	// 将 cfd3 添加到读集合
while (1) {nready = select(cfd3+1, &rset, NULL, NULL, NULL);
}

select 优缺点

  • 缺点:

    • select 返回值不能描述,具体满足对应事件的描述符是哪一个!
    • 需要使用 遍历方法,找寻那个满足事件的 fd。
    • 在一个进程中,最多只支持 1024 客户端链接请求。
  • 优点:

    • 跨平台!win、Linux、MacOs、Unix、类Unix、mips …
  • 特性:select 实现多路IO转接并发服务器的性能,并不比 poll、epoll 低。

练习

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>#define SRV_PORT 10086
#define BUF_SIZE 1024
int test01()
{int ret = -1;int lfd = -1;int cfd = -1;int maxfd = 0;char buf[BUF_SIZE];//初始化服务器地址struct sockaddr_in srv_addr;memset(&srv_addr, 0, sizeof(srv_addr));srv_addr.sin_family = AF_INET;srv_addr.sin_port = htons(SRV_PORT);srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//用于接收客户端地址struct sockaddr_in clt_addr;socklen_t clt_addr_len = sizeof(clt_addr);fd_set rset; // 读集合fd_set allset;//监听集合lfd = socket(AF_INET, SOCK_STREAM, 0);if(-1 == lfd){perror("socket");}bind(lfd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));listen(lfd, 128);maxfd = lfd;//清空监听集合FD_ZERO(&allset);//将lfd 添加到集合中FD_SET(lfd, &allset);while(1){//rset = allset;ret = select(maxfd+1, &rset, NULL, NULL, NULL); //监听读集合if(ret < 0){perror("select");}//判断lfd 是否在传出的读集合中if(FD_ISSET(lfd, &rset)){//满足都事件cfd = accept(lfd, (struct sockaddr*)&clt_addr, &clt_addr_len);FD_SET(cfd, &allset);//将通信的cfd 添加到监听集合中if(maxfd < cfd) //更新maxfd{maxfd = cfd;}if(ret == 1) //只有一个fd满足读事件,并且已经处理完成{continue;}}//处理数据通信for(int i = lfd + 1; i < maxfd + 1; i ++){//判断读集合中的 cfdif(FD_ISSET(i, &rset)){ret = read(i, buf, BUF_SIZE);if(0 == ret){           close(i);FD_CLR(i, &allset);  //移除已关闭的cfd}for(int j = 0; j < ret; ++j){buf[j] = toupper(buf[j]);}write(i, buf, ret);//输出到屏幕write(STDOUT_FILENO, buf, ret);}}}close(lfd);return 0;
}

文章转载自:

http://eReKSM2k.bkctL.cn
http://5jLHtWe2.bkctL.cn
http://MDt0w87G.bkctL.cn
http://gR6oNuTI.bkctL.cn
http://SF4pQxw6.bkctL.cn
http://W3QKOmib.bkctL.cn
http://XmCvrrlt.bkctL.cn
http://joNiz8Kp.bkctL.cn
http://axzqGQup.bkctL.cn
http://wclNKGRZ.bkctL.cn
http://4yrDRHfS.bkctL.cn
http://2T3QA1DU.bkctL.cn
http://gvUvshVo.bkctL.cn
http://SHWaCt2D.bkctL.cn
http://n2whkTYU.bkctL.cn
http://Tqb5JdUw.bkctL.cn
http://C597Li78.bkctL.cn
http://3AiMUUOK.bkctL.cn
http://cJplbgVu.bkctL.cn
http://uoc94i0r.bkctL.cn
http://r6VQe43W.bkctL.cn
http://o5iplUl3.bkctL.cn
http://zgZEMGO0.bkctL.cn
http://qYg9G8EW.bkctL.cn
http://8ZBmsEyh.bkctL.cn
http://YW6so070.bkctL.cn
http://z1Hp660l.bkctL.cn
http://mlJmVhzI.bkctL.cn
http://0bpIYJXb.bkctL.cn
http://q2HhiOIS.bkctL.cn
http://www.dtcms.com/a/378214.html

相关文章:

  • 【WRF-VPRM 预处理器】HEG 安装(服务器)-MRT工具替代
  • 你知道服务器和电脑主机的区别吗?
  • 接力邓承浩,姜海荣能讲好深蓝汽车新故事吗?
  • 广东充电芯片助力新能源汽车车载系统升级
  • 大数据电商流量分析项目实战:Day2-1 补充Mysql和sql安装和学习
  • 【Unity UGUI 交互组件——Dropdown(TMP版本)(10)】
  • 自动化拨号爬虫体系:虚拟机集群部署与增量管理
  • 【机器人运动学】正运动学分析
  • 基于机器学习的P2P网贷平台信用违约预测模型
  • 工厂怎么认证iso14067
  • flutter项目 -- 换logo、名称 、签名、打包
  • 【Windows】VMware安装Ubuntu操作系统
  • 仿函数的分析与应用
  • 框架漏洞详解
  • Day02 集合 | 30. 串联所有单词的子串、146. LRU 缓存、811. 子域名访问计数
  • 基于springboot的教育资源共享管理系统
  • 汽车网络安全 CyberSecurity ISO/SAE 21434 测试之一
  • Fiddler
  • 【软件设计师(中级)】P1 计算机系统知识(待完成)
  • KronosTokenizer结构解析
  • (网络编程)网络编程套接字 UDP的socket API 代码解析
  • iPhone17系列发布!跨端如何破局?
  • 把nginx、jar包、redis做成windows系统服务,开机自动启动
  • Java学习笔记四(继承)
  • Redis分布式锁的try-with-resources实现
  • 广东省省考备考(第九十七天9.11)——言语(刷题巩固第三节课)
  • ReentrantLock 源码深度解析
  • 机器人驭风而行:低空经济如何开启智能新纪元
  • 【系统架构设计(27)】信息安全技术集成
  • spring mvc 拦截器 (HandlerInterceptor )