![为什么 TCP 每个数据包发送超过 1 个 ack?](https://linux22.com/image/1504345/%E4%B8%BA%E4%BB%80%E4%B9%88%20TCP%20%E6%AF%8F%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%8C%85%E5%8F%91%E9%80%81%E8%B6%85%E8%BF%87%201%20%E4%B8%AA%20ack%EF%BC%9F.png)
我的源发送了 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
答案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 是不好的。这会导致问题,并且不会产生任何效果