欢迎交流 QQ 2431173627 微信 ccc17862701790
存在问题
用socket基本的一套api已经可以构建一个简单的tcp服务器了
思路就是 加一个while循环 在循环里面服务器程序用socket bind listen accept recv send 一条龙
具体可以看我写的这一篇博客 socket网络编程基础篇-------如何写一个简单的TCP服务器
但是这样简单的tcp服务器在只有单个客户端请求的时候是可以应付的,但是在有多个客户端请求的时候是存在很大问题的
以下面的场景作为例子
----->进入while循环
--->服务器用socket创建监听套接字(比如该套接字的文件描述符号为4)
-->调用listen函数监听该套接字
-->新来一个客户端调用connect请求连接
--->服务器调用accpet函数接受客户端请求并创建了针对这个客户端的数据传输套接字(比如文件描述符号为5)
--->在这个套接字5上调用read函数读客户端发过来的数据
-->新来一个客户端调用connect请求连接
--->服务器调用accpet函数接受客户端请求并创建了针对这个客户端的数据传输套接字(比如文件描述符号为6)
--->在这个套接字6上调用read函数读客户端发过来的数据
-->新来一个客户端调用connect请求连接
--->服务器调用accpet函数接受客户端请求并创建了针对这个客户端的数据传输套接字(比如文件描述符号为7)
--->在这个套接字7上调用read函数读客户端发过来的数据
........(上述过程在服务器端用while循环 多个客户端请求的时候就不断延续上述过程)
上述的这样一个过程存在一个严重的问题 在多个客户端有连接请求或者读写请求的时候
当使用accpet函数的时候发现没有客户端连接时会阻塞,
同样当使用read/write函数的时候发现客户端没有数据传过来时也会阻塞
所以在上述多个客户端请求的过程中,
(1)假如在某个循环中调用read函数阻塞了,这个时候假如又来了一个客户端连接
由于现在服务器端程序卡在了read这里
就没办法进入下一次循环到accept那里 ,这样的环这个想建立连接的客户端就一直阻塞在那里
(2)假如在某一个循环调用accept阻塞了,服务端程序由于卡在accept这里不能往下执行到read函数
故也响应不了前面已经建立连接的客户端套接字发过来的数据,这样根本就不能处理多个客户端的服务请求,
导致客户端的请求大大延迟
那怎么办呢?所以就引入了多路io复用,
他有三种实现机制----select函数,poll函数,epoll函数 这里先介绍select
设计思路
对于select函数工作过程的理解
select函数是怎么工作的呢?我是这么理解的
上面这个服务器客户端交互过程本质上是文件io函数(accept/read)对文件描述符(4,5,6,7)的操作过程.
出现问题的罪魁祸首就是,
accep/read函数"自作主张"就直接去连接/读取文件描述符对应的套接字,
丝毫不管对应文件描述符的套接字是否可以连接/读取
万一对应文件描述符的套接字没有连接/数据请求传输过来,这两个函数自然就会阻塞.
理想的情况应该是请一个"监控员" ,
在执行read/accept之前 先让这个监管员依次检查一番
看哪个文件描述符有连接过来了或者有数据传输过来了
这时候再调用accept/read函数就不会阻塞了
如果监管员这一轮查找 没看到哪个文件描述符有连接过来了或者有数据传输过来了
就在进入下一轮的检查 就不调用accept或者read
虽然在这个监管员工作也会耽搁一定的时间(select每次检查都是阻塞查询) 但是比起accept/read函数盲目的就上来读写一个文件描述符 然后卡在那大半天 效率明显来的高
select就起了这样一个"监管员"的作用,