【发布时间】:2017-10-05 13:41:17
【问题描述】:
我知道为什么要使用它,但我不确定将 setsockopt 放在我的套接字代码中的什么位置。
我很清楚它可以通过套接字 api 的内部机制进行修改,但是我应该在什么时候使用 setsockopt 设置 TCP_QUICKACK 选项?
我应该在创建套接字时设置它,然后在(或之前?)每次接收和发送之后?还是只接收?
我是否应该检查该选项是否已设置?
【问题讨论】:
我知道为什么要使用它,但我不确定将 setsockopt 放在我的套接字代码中的什么位置。
我很清楚它可以通过套接字 api 的内部机制进行修改,但是我应该在什么时候使用 setsockopt 设置 TCP_QUICKACK 选项?
我应该在创建套接字时设置它,然后在(或之前?)每次接收和发送之后?还是只接收?
我是否应该检查该选项是否已设置?
【问题讨论】:
什么时候应该设置 TCP_QUICKACK 选项?
IETF 提供TCP Tuning for HTTP, draft-stenberg-httpbis-tcp-03。文档第 4.4 节说明:
延迟 ACK [RFC1122] 是一种在大多数 TCP 堆栈中启用的机制, 导致堆栈延迟发送确认数据包作为响应 到数据。 ACK 延迟到某个阈值,或者直到 对等方有一些数据要发送,在这种情况下将发送 ACK 连同该数据。取决于流量和 TCP 堆栈 这个延迟可以长达500ms。
这与启用了 Nagle 算法的对等方的交互很差。 因为 Nagle 的算法延迟发送直到有一个 MSS 数据 提供或,直到收到所有发送数据的 ACK,延迟 ACK 可以强制 Nagle 算法在不缓冲数据包时进行缓冲 需要(即,当其他对等方已经处理了 优秀的数据)。
延迟的 ACK 在合理的情况下很有用 假设一个数据包几乎会立即(在 500 毫秒内)导致 向另一个方向发送数据。通常在 HTTP/1.1 中 而 HTTP/2 这不太可能:因此,禁用延迟 ACK 可以 改善延迟。
但是,TLS 握手显然是这种情况的例外。为了 保持 TLS 握手的持续时间可能很有用 已启用延迟 ACK。
此外,对于可以保证响应的低延迟服务器 500 毫秒内的请求,在长时间运行的连接(例如 HTTP/2)上, 当请求小到可以放入一个小数据包时, 开启延迟的 ACK 可能会带来较小的性能优势。
有效使用关闭延迟的 ACK 需要大量的 分析。
在文档的后面,它提供了以下内容:
在最近的 Linux 内核上(自 Linux 2.4.4 起),延迟 ACK 可以 像这样禁用:
int one = 1; setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));与禁用 Nagle 算法不同,在 Linux 上禁用延迟 ACK 是 不是一次性操作:TCP 堆栈内的处理可能会导致 重新启用延迟的 ACK。因此,使用 TCP_QUICKACK 有效地需要在设置和取消设置套接字选项 连接的生命周期。
【讨论】: