为什么 TCP 每个数据包发送超过 1 个 ack?

为什么 TCP 每个数据包发送超过 1 个 ack?

我的源发送了 4794 字节的数据包(至少根据捕获的数据,每个数据包看起来像是 1 个数据包),但是,目标计算机发送2 次确认为了每一个从源发送的数据包。
我尝试将目标机器的读取堆栈大小 ( /proc/sys/net/ipv4/tcp_rmem) 更改为高于 4906(默认最小值)的值,但没有看到任何变化。
两个系统都运行 linux(centos)。
我使用tcpdump“wireshark”来分析捕获。

以下是 wireshark 的截图:

在此处输入图片描述

源地址是 172.16.33.237,目的地址是 172.16.34.111。
请注意,每个 4794 数据包都会收到 2 个确认。194
字节数据包是目标应用程序的响应(我认为这与本讨论无关)

答案1

大量使用 NIC大段卸载其中 NIC 驱动程序负责将 TCP 数据切割成更小的数据包进行传输,而不是系统 CPU。tcpdump/Wireshark 在被 NIC 切割之前捕获流量,这就是为什么有时您可以在捕获中看到大于接口 MTU 的数据包。

假设使用 1500 字节的标准 MTU,则需要发送 4 个数据包。TCP延迟确认是另一个性能特征,通常会导致每隔一个数据包发送一个 ACK​​。

答案2

阅读全文这里

您可以调整 TCP 缓冲区大小。首先请输入以下命令来检查配置的值:

$ cat /proc/sys/net/ipv4/tcp_mem

查找接收套接字内存的最大容量:

$ cat /proc/sys/net/core/rmem_default

$ cat /proc/sys/net/core/rmem_max

对于发送套接字内存:

$ cat /proc/sys/net/core/wmem_default

$ cat /proc/sys/net/core/wmem_max

内存缓冲区的最大数量:

$ cat /proc/sys/net/core/optmem_max

调整值(wmem 和 rmem):

您必须在所有协议上将最大发送 wmem 和接收 rmem 缓冲区大小设置为 12 MB。请按照以下命令操作:

# echo 'net.core.wmem_max=12582912' >> /etc/sysctl.conf

# echo 'net.core.rmem_max=12582912' >> /etc/sysctl.conf

设置最小、初始和最大大小(以字节为单位):

# echo 'net.ipv4.tcp_rmem= 10240 87380 12582912' >> /etc/sysctl.conf

# echo 'net.ipv4.tcp_wmem= 10240 87380 12582912' >> /etc/sysctl.conf

扩大转会窗口:

# echo 'net.ipv4.tcp_window_scaling = 1' >> /etc/sysctl.conf

启用 RFC1323 中定义的时间戳:

# echo 'net.ipv4.tcp_timestamps = 1' >> /etc/sysctl.conf

启用确认:

# echo 'net.ipv4.tcp_sack = 1' >> /etc/sysctl.conf

如果在关闭连接时设置了根缓存的连接指标,则:

# echo 'net.ipv4.tcp_no_metrics_save = 1' >> /etc/sysctl.conf

设置输入端的最大数据包数量:

# echo 'net.core.netdev_max_backlog = 5000' >> /etc/sysctl.conf

请重新加载更改:

# sysctl -p

查看更改:

# tcpdump -ni eth0

答案3

MarkoPolo 是正确的。但他没有提到,如果您使用网络分路器,您将在数据包通过网络发送时捕获它们,这会更有意义。您看到的是 3 个数据包合并为一个。接收 TCP 正在利用延迟 ACK 并确认每一个或两个数据包。

由于发送设备的停止和等待行为,194 字节应用程序响应是相关的。这种模式正是引发您提出问题的原因。如果这只是一个没有服务器响应的单向批量传输,那么就会出现非常不同的模式。

此外,在具有默认路由的网络上将 MTU 设置为 9000 是不好的。这会导致问题,并且不会产生任何效果

相关内容