参考《windows网络编程》第五章。为巩固知识,以问题作为驱动,检查知识点。
windows下 Select模型
1. Select模型有什么作用?
可以判断指定套接字上是否有数据存在、是否可以写入数据。防止因为使用send或recv过程引起的阻塞状态。
2. Select模型有什么优点?
可以减少原有阻塞模型需要使用的多个线程,减少资源消耗。
3. Select函数原型是什么?
Int select(
Int nfds,//忽略不用
Fd_set FAR *readfds,
Fd_set FAR *writefds,
Fd_set FAR *exceptfds,
Const struct timeval FAR * timeout
);
4. Readfds集合的条件是什么?
Readfds检查可读性,当以下任一条件成立时,对应的socket会保留在select返回后的readfds中:
*有数据可以读入
*连接已经被关闭、重启或者终止
*如果已经调用了listen,而且有一个连接正在等待建立,即将在accept返回成功
5. Writefds集合的条件是什么?
Writefds检查可写性,当以下任一条件成立时,对应的socket会保留在select返回后的Writefds中:
*有数据可以发送
*如果一个非阻塞连接请求正在被处理,并且连接已经成功
6. Exceptfds集合的条件是什么?
Exceptfds检查例外socket状态,Exceptfds当以下任一条件成立时,对应的socket会保留在select返回后的exceptfds中:
*如果一个非阻塞连接请求正在被处理,并且连接尝试失败
*有OOB(out of band)数据可供读取
7. 怎么测试一个套接字是否可读?
将套接字s加入到readfds集合中,然后调用select函数等待完成;当select完成之后,判断套接字s是否仍在readfds集合中;如果是则表明有数据可读,可立即着手从上面读取数据。如果不在集合中则没有可读数据。
8. 三个集合中可以同时为空吗?
不可以,必须有一个或以上集合为非空,select才能等待。
9. Select会阻塞吗?哪个参数条件决定?
在所有三个集合中的条件都没有发生的情况下会阻塞;阻塞多少时间由timeval参数决定。如果timeout指针为空,则会一直阻塞直到三个集合中有条件成立。
10. 如果timeval设置为0,会出现什么情况?
如果timeval设置为0,select操作在检查了三个集合中的状态后立即返回,允许程序对select操作进行轮询。但出于性能考虑,应避免这样的设置。
11. 对集合的操作宏有四个,分别是什么?
FD_ZERO(*set) 将集合s初始化为空集
FD_CLR(s,*set) 从set中删除套接字
FD_ISSET(s,*set) 检查s是否在set集合中
FD_SET(s,*set) 将套接字s加入集合s中
12. Select操作一个或多个套接字句柄的过程是怎么样的?
*用 FD_ZERO初始化自己感兴趣的fd_set
*用FD_SET将套接字分配给需要使用的fd_set
*调用select函数,并设置超时时长
*select函数返回值表示已经等待成功的socket的数据,并且返回时,对应的fd_set只剩下有对应条件发生的套接字集合;使用FD_ISSET对集合是否包含套接字做检查
*对每个集合中有对应事件发生的套接字做数据处理
*重新回到第一步,初始化fd_set
13. Fd_set结构有什么限制?怎么突破这个限制?
Fd_set结构的大小FD_SETSIZE在winsock2.h中定义只能放64个套接字。如果要加大这个值,在包含winsock2.h之前将FD_SETSIZE定义为自己希望的大小。
14. 对于比较多的套接字,select有什么劣势?
Select模型使用三个集合来检查是否有某些条件成立,就意味着如果有1000个套接字,就需要在调用select之前使用FD_SET把这1000个套接字都加入到感兴趣的集合中;并且有事件发生的时候,要检查所有套接字是否 在各个集合中,会影响服务程序运行的效率。