96SEO 2026-02-23 13:42 8
IO多路转接也称为IO多路复用它是一种网络通信的手段机制通过这种方式可以同时监测多个文件描述符并且这个过程是阻塞的一旦检测到有文件描述符就绪

可以读数据或者可以写数据程序的阻塞就会被解除之后就可以基于这些一个或多个就绪的文件描述符进行通信了。
通过这种方式在单线程/进程的场景下也可以在服务器端实现并发。
常见的IO多路转接方式有select、poll、epoll。
下面先对多线程/多进程并发和IO多路转接的并发处理流程进行对比服务器端
如果没有新的客户端的连接请求当前线程/进程会阻塞如果有新的客户端连接请求解除阻塞建立连接
接收客户端发送的通信数据如果没有通信数据当前线程/进程会阻塞数据到达之后阻塞自动解除调用
给客户端发送数据如果写缓冲区已满当前线程/进程会阻塞否则将待发送数据写入写缓冲区中
使用IO多路转接函数委托内核检测服务器端所有的文件描述符通信和监听两类这个检测过程会导致进程/线程的阻塞如果检测到已就绪的文件描述符阻塞解除并将这些已就绪的文件描述符传出根据类型对传出的所有已就绪文件描述符进行判断并做出不同的处理
此时调用accept()是不会导致程序阻塞的因为监听的文件描述符是已就绪的有新请求
不会阻塞程序因为通信的文件描述符是就绪的读缓冲区内已有数据调用
不会阻塞程序因为通信的文件描述符是就绪的写缓冲区不满可以往里面写数据
与多进程和多线程技术相比I/O多路复用技术的最大优势是系统开销小系统不必创建进程/线程也不必维护这些进程/线程从而大大减小了系统的开销。
使用select这种IO多路转接方式需要调用一个同名函数select这个函数是跨平台的Linux、Mac、Windows都是支持的。
程序猿通过调用这个函数可以委托内核帮助我们检测若干个文件描述符的状态其实就是检测这些文件描述符对应的读写缓冲区的状态
读缓冲区检测里边有没有数据如果有数据该缓冲区对应的文件描述符就绪写缓冲区检测写缓冲区是否可以写(有没有容量)如果有容量可以写缓冲区对应的文件描述符就绪读写异常检测读写缓冲区是否有异常如果有该缓冲区对应的文件描述符就绪
委托检测的文件描述符被遍历检测完毕之后已就绪的这些满足条件的文件描述符会通过select()的参数分3个集合传出程序猿得到这几个集合之后就可以分情况依次处理了。
内核需要线性遍历这些集合中的文件描述符这个值是循环结束的条件在Window中这个参数是无效的指定为-1即可
传入传出参数读集合一般情况下都是需要检测的这样才知道通过哪个文件描述符接收数据
timeout超时时长用来强制解除select()函数的阻塞的
NULL函数检测不到就绪的文件描述符会一直阻塞。
等待固定时长秒函数检测不到就绪的文件描述符在指定时长之后强制解除阻塞函数返回0不等待函数不会阻塞直接将该参数对应的结构体初始化为0即可。
大于0成功返回集合中已就绪的文件描述符的总个数等于-1函数调用失败等于0超时没有检测到就绪的文件描述符
另外初始化fd_set类型的参数还需要使用相关的一些列操作函数具体如下
在select()函数中第2、3、4个参数都是fd_set类型它表示一个文件描述符的集合类似于信号集
sigset_t这个类型的数据有128个字节也就是1024个标志位和内核中文件描述符表中的文件描述符个数是一样的。
文件描述符表中的每一个文件描述符是一一对应的关系这样就可以使用最小的存储空间将要表达的意思描述出来了。
下图中的fd_set中存储了要委托内核检测读缓冲区的文件描述符集合。
如果集合中的标志位为0代表不检测这个文件描述符状态如果集合中的标志位为1代表检测这个文件描述符状态
内核在遍历这个读集合的过程中如果被检测的文件描述符对应的读缓冲区中没有数据内核将修改这个文件描述符在读集合fd_set中对应的标志位改为0如果有数据那么这个标志位的值不变还是1。
当select()函数解除阻塞之后被内核修改过的读集合通过参数传出此时集合中只要标志位的值为1那么它对应的文件描述符肯定是就绪的我们就可以基于这个文件描述符和客户端建立新连接或者通信了。
循环调用select()周期性的对所有的文件描述符进行检测select()
如果客户端和服务器断开了连接使用FD_CLR()将这个文件描述符从检测集合中删除如果没有断开连接正常通信即可
htons(9999);addr.sin_addr.s_addr
这里timeout参数一定要设置为结构体要么就设为NULLNULL就是默认阻塞struct
(socklen_t*)cliLen);printf(%d\n,cfd);//
判断从监听的文件描述符之后到maxfd这个范围内的文件描述符是否读缓冲区有数据i
strlen(buf)1);printf(读取了数据回传给客户端\n);}else{//
-1){perror(connect);exit(0);}//
客户端不需要使用IO多路转接进行处理因为客户端和服务器的对应关系是
1N也就是说客户端是比较专一的只能和一个连接成功的服务器通信。
虽然使用select这种IO多路转接技术可以降低系统开销提高程序效率但是它也有局限性
待检测集合第2、3、4个参数需要频繁的在用户区和内核区之间进行数据的拷贝效率低内核对于select传递进来的待检测集合的检测方式是线性的
如果集合内待检测的文件描述符很多检测效率会比较低如果集合内待检测的文件描述符相对较少检测效率会比较高
使用select能够检测的最大文件描述符个数有上限默认是1024这是在内核中被写死了的。
select里面的timeout参数一定要设置为结构体要么就设为NULLNULL就是默认阻塞
调试可以发现服务端怎么工作的select循环只有当有空闲文件描述符的时候分逻辑到底是连接还是通信的。
如果是通信的会记录是否读完了数据如果读完了内核会将文件描述符重新标记为0除非重新写入数据。
但是上面的客户端代码有个问题就是服务端多次写入的时候客户端只能收到前面10个字节的数据但是如果循环调用read客户端read会阻塞因为这里服务端是不会主动发送数据的只是把客户端传过来的数据重新传回去。
想一下怎么解决这个问题
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback