c - select() 是否可以为没有排队数据的套接字返回准备就绪?
问题描述
我正在阅读 R.Stevens 的 UNIX Network Programming,以下仅包含相关部分的代码片段取自其中。它是一个回声服务器。
fd_set rset, allset;
int nready, client[FD_SETSIZE];
...
for( ; ; ) {
rset = allset;
nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
....
for( i = 0; i <= maxi; i++){
if ( (sockfd = client[i]) <= 0)
continue;
if (FD_ISSET(sockfd, &rset)){
if( (n = read(sockfd, buf, MAXLINE)) == 0){
close(sockfd);
FD_CLEAR(sockfd, &allset);
client[i] = -1;
} else
writen(sockfd, buf, n);
...
}
}
我将简要描述变量:client
是一个包含分配给连接客户端的文件描述符的数组;-1 代表自由进入。是准备读取的fdnready
的数量。是一个保存位的结构,用于指定哪个fd已准备就绪。是一个相同类型的结构,表示必须由 测试的fd。rset
allset
select()
内部for
循环检查来自每个连接的客户端的传入数据(这通过 FD_ISSSET 宏进行测试)。如果有任何待处理的数据,服务器会将其写回客户端。如果read()
返回 0,则表示客户端已向服务器发送了 FIN,因此它终止与 的连接close()
。
现在的问题是:作者说我刚刚展示的服务器有问题。事实上,考虑一个连接到服务器的恶意客户端,发送一个字节的数据,而不是换行符,然后进入睡眠状态。服务器将调用read()
,读取该字节,然后阻止对 的下一次调用read()
,等待来自该客户端的更多数据,从而拒绝向所有其他客户端提供服务。我不明白为什么服务器应该在下一次调用read()
: 之前阻塞,在下一次调用之前read()
,select()
将返回每个连接的套接字的就绪状态,并且由于我们的客户端没有发送更多数据(一个字节已经被消耗),未设置此客户端的就绪状态位。因此,if
没有输入客户端的块,并且read()
不叫。这很好,除非select()
可以为没有数据排队的套接字返回准备就绪,我认为这是不可能的。那么我错在哪里?
解决方案
推荐阅读
- office-ui-fabric - 从 office UI 结构中获取 iconNames 列表
- reactjs - 在 Redux 中,有 Data Provider 的概念吗?
- html - 如何在 ASP.NET 中使用 innerhtml 制作按钮事件
- python - 另一个 BeautifulSoup 错误“charmap”编解码器无法编码字符
- firebase - 我可以在登录帐户时注册新用户并进行身份验证吗?(Firebase 身份验证)
- java - 如何以更有效的方式遍历像素?
- c - Linux C 定时器 - 信号中断当前进程
- python - 当我在 Python 中出现 MemoryError 时,我可以使用我的硬盘作为内存吗?
- devise - Sidekiq Web 使 nil:NilClass 的未定义方法“failure_app”失败
- java - java - 如何通过java中的分页处理通过网络调用的巨大json?