select() 是否保证所有数据都可用于从套接字读取或仅部分数据
Does select() guarantee that all data is available for reading from a socket or only part of the data
我有一个用c写的单线程多客户端程序。
如果一个客户端的网络连接速度慢得可怕或者是恶意的,并且将他们的 send() 到服务器应用程序的速率限制为 1 byte/second 之类的荒谬的东西,select() return 在从客户端接收到第一个字节时(因为套接字已激活),然后在等待写入额外的 2000 个字节时让 read() 调用处于阻塞状态,从而完全破坏服务器并使其无法访问其他客户;或者 select 仅在恶意客户端已将所有字节写入某些 OS 缓冲区时仅 return 起作用,允许服务器同时处理其他客户端?
来自the POSIX documentation about select
:
A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK
clear would not block, whether or not the function would transfer data successfully.
和
A descriptor shall be considered ready for writing when a call to an output function with O_NONBLOCK
clear would not block, whether or not the function would transfer data successfully.
因此,所有可以保证的是,如果您尝试接收(对于读取集中的套接字)或发送(对于写入集中的套接字),阻塞套接字将不会阻塞。
您将接收或能够发送的字节数不确定。
这就是为什么接收和发送经常使用循环和非阻塞套接字完成的原因。
另请注意,此 "would not block" 和 "whether or not the function would transfer data successfully" 可能意味着接收或发送呼叫可能 return 立即出现错误。或者在接收的情况下,return 的值为 0
,这意味着基于连接的连接已被对等方关闭。
OS 怎么知道它必须等待 2000 个字节到达? TCP 是一个流,因此 OS 无法知道在 1999 字节之后还有一个字节未决。
对于 UDP,OS 知道它是基于数据包的,一旦最后一个字节到达,它就会让整个数据包可用。它不能提前传送第一个字节,因为 UDP 校验和必须在整个数据包中进行验证。
我有一个用c写的单线程多客户端程序。
如果一个客户端的网络连接速度慢得可怕或者是恶意的,并且将他们的 send() 到服务器应用程序的速率限制为 1 byte/second 之类的荒谬的东西,select() return 在从客户端接收到第一个字节时(因为套接字已激活),然后在等待写入额外的 2000 个字节时让 read() 调用处于阻塞状态,从而完全破坏服务器并使其无法访问其他客户;或者 select 仅在恶意客户端已将所有字节写入某些 OS 缓冲区时仅 return 起作用,允许服务器同时处理其他客户端?
来自the POSIX documentation about select
:
A descriptor shall be considered ready for reading when a call to an input function with
O_NONBLOCK
clear would not block, whether or not the function would transfer data successfully.
和
A descriptor shall be considered ready for writing when a call to an output function with
O_NONBLOCK
clear would not block, whether or not the function would transfer data successfully.
因此,所有可以保证的是,如果您尝试接收(对于读取集中的套接字)或发送(对于写入集中的套接字),阻塞套接字将不会阻塞。
您将接收或能够发送的字节数不确定。
这就是为什么接收和发送经常使用循环和非阻塞套接字完成的原因。
另请注意,此 "would not block" 和 "whether or not the function would transfer data successfully" 可能意味着接收或发送呼叫可能 return 立即出现错误。或者在接收的情况下,return 的值为 0
,这意味着基于连接的连接已被对等方关闭。
OS 怎么知道它必须等待 2000 个字节到达? TCP 是一个流,因此 OS 无法知道在 1999 字节之后还有一个字节未决。
对于 UDP,OS 知道它是基于数据包的,一旦最后一个字节到达,它就会让整个数据包可用。它不能提前传送第一个字节,因为 UDP 校验和必须在整个数据包中进行验证。