select() 是否保证所有数据都可用于从套接字读取或仅部分数据

问题描述 投票:0回答:2

我有一个用c编写的单线程多客户端程序。

如果一个客户端的网络连接速度慢得可怕,或者是恶意的,并将其发送到服务器应用程序的 send() 速率限制为可笑的值,例如 1 字节/秒,则 select() 将返回从客户端收到的第一个字节(如套接字已变为活动状态),然后在等待写入额外的 2000 字节时让 read() 调用处于阻塞状态,从而完全破坏服务器并使其他客户端无法访问它;或者只有当恶意客户端将所有字节完全写入某个操作系统缓冲区时,选择函数才会返回,从而允许服务器同时处理其他客户端?

c sockets recv posix-select
2个回答
3
投票

来自 有关

select
的 POSIX 文档:

当使用

O_NONBLOCK
清除输入函数的调用不会阻塞时,无论该函数是否成功传输数据,描述符都应被视为已准备好读取。

当使用

O_NONBLOCK
清除对输出函数的调用不会阻塞时,无论该函数是否成功传输数据,描述符都应被视为已准备好写入。

因此,可以保证的是,如果您尝试接收(对于读集中的套接字)或发送(对于写集中的套接字),阻塞套接字不会阻塞。

您将接收或能够发送的字节数是不确定的。

这就是为什么接收和发送经常使用循环和非阻塞套接字完成。

另请注意,“不会阻塞”和“函数是否会成功传输数据”可能意味着接收或发送调用可能会立即返回并出现错误。或者在接收的情况下,返回值

0
,这意味着基于连接的连接被对等方关闭。


0
投票

操作系统如何知道它必须等待 2000 字节到达? TCP 是一个流,因此操作系统在 1999 个字节之后无法知道还有一个字节待处理。

对于 UDP,操作系统知道它是基于数据包的,一旦最后一个字节到达,它将拥有整个数据包。它无法提前传送第一个字节,因为必须对整个数据包验证 UDP 校验和。

© www.soinside.com 2019 - 2024. All rights reserved.