day09
本章目标
select
- 读、写、异常事件发生条件
- 用
select
改进回射服务器程序
select
再复习和补充一点
select
的参数
1 | #include <sys/select.h> |
参数一:
int nfds
因为
select
的对感兴趣的fd
取值范围为[0, nfds)
,前闭后开区间,所以需要最大的文件描述符+1
,才能覆盖整个感兴趣的文件描述符号的范围。参数二:
fd_set *readfds
可读事件集合,添加感兴趣可读
fd
参数三:
fd_set *writefds
可写事件集合,添加感兴趣可写
fd
参数四:
fd_set *exceptfds
异常事件集合
参数五:
struct timeval *timeout
超时时间,在响应的超时时间内没有发生任何一个
I/O事件
(读/写事件),则select
返回0
,指示超时。出现错误select
返回-1
.
监测到多个事件,需要遍历,
readfds
、writefds
、exceptfds
这些集合来一一处理这些事情,则将select
实现的服务器称为并发服务器。因为没有能力并行处理这些I/O
事件,只能一一遍历处理这些事件。所以称为并发服务器,而不是并行服务器。并发服务器不能长时间处理这些事件,因为长时间处理则不能去执行其他的动作。且事件间的处理间隔时间也不能太长。无法充分利用多核处理器。使用多进程select
或者多线程处理这些事件。
select
可以同时检测网络I/O
和标准I/O
事件。那个事件产生则处理那个事件。不会因为某一个阻塞导致另一个无法处理。
读、写、异常事件发生条件
- 可读
- 套接口缓冲区有数据可读,底层本质:如果缓冲区的数据超过一定的范围才会通知有数据可读
- 连接的读一般关闭,即接收到
FIN
段,读操作返回0
- 如果是监听套接口,已完成连接队列不为空时。
- 套接口上发生了一个错误待处理,错误可以通过
getsockopt
指定SO_ERROR
选项来获取
- 可写
- 套接口发送缓冲区有空间容纳数据
- 连接的写一半关闭,即收到
RST
段之后,再次调用write
操作 - 套接口上发生一个错误待处理,错误可以通过
getsockopt
指定SO_ERROR
选项来获取
- 异常
- 套接口存在带外数据。
并发服务器
对上一次的服务器端通过
select
使用一个进程实现。并发服务器的连接客户端的限制,FD_SETSZIE
大小和一个进程当中能够打开的I/O
的最大数目。FD_SETSIZE
不能被更改(非要更改,需要更改内核代码,并进行重新编译),而一个进程的可以打开的最大的I/O
数目可以更改,通过ulimit -n 1000
命令更改一个进程可以打开的最大I/O
数目为1000
。FD_SETSIZE
默认情况下和进程能够打开的最大I/O
数目为1024
个。
核心代码(部分代码)
1 | int i = 0; |