在前面的博客中写过TCP协议的服务端的编程流程
但是有一个小问题,就是每一次发送数据都要建立一次三次握手,多次发送和接受数据可能很多时间都浪费在三次握手这个过程中。
所以当一个客户端和服务端建立连接后,完成整个交互过程(和服务器存在多次的收发数据)之后,再断开连接,能够很好的提高效率。
I/O复用使得程序能同时监听多个文件描述符。在下面这几种情况下需要使用I/O复用技术:
- TCP服务器同时要处理监听套接字和连接套接字
- 服务器要同时处理TCP请求和UDP请求
- 程序要同时处理多个套接字
- 客户端程序要同时处理用户输入和网络连接
- 服务器要同时监听多个端口
IO复用对于服务器的意义:
一个线程通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力。
select API
1 |
|
1 | maxfd:设置为所有监听的文件描述符的最大值+1 |
fd_set结构
fd_set包含一个32个元素的long int类型的数组:32*32=1024 bit
使用每一个比特位记录一个文件描述符,文件描述符的值在位移上表现。
select优点:
select模型是Windows sockets中最常见的IO模型。它利用select函数实现IO 管理。通过对select函数的调用,应用程序可以判断套接字是否存在数据、能否向该套接字写入据。
如:在调用recv函数之前,先调用select函数,如果系统没有可读数据那么select函数就会阻塞在这里。当系统存在可读或可写数据时,select函数返回,就可以调用recv函数接 收数据了。
可以看出使用select模型,需要两次调用函数。第一次调用select函数第二次socket API。使用该模式的好处是:可以等待多个套接字。
select缺点:
(1)每次调⽤用select,都需要把fd集合从⽤用户态拷贝到内核态,这个开销在fd很多时会很⼤大
(2)同时每次调⽤用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很⼤大
(3)select⽀支持的⽂文件描述符数量太⼩小了,默认是1024
直接上代码
服务端
1 |
|
客户端
1 |
|