tcp - 如何在 tcpdump 中捕获 TCP/IP 碎片?
问题描述
众所周知,MTU是1500,TCP的MSS是1460。所以当recv函数中使用的buf大于1460字节时,TCP会被拆分成很多部分。
我写了一个简单的 echo prog,想用 tcpdump 来检查碎片。但是在buf很小的时候不显示分片,而是在buf在20K左右的时候显示。
这是代码:
服务器:
import socket
import sys
import os
addr = ('10.0.0.2',10086)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(addr)
server.listen(5)
while True:
connfd, addr= server.accept()
print 'connection ip:', addr
data = connfd.recv(8192);
客户:
import socket
import os
import sys
addr = ('10.0.0.2', 10086)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)
data = '';
for num in range(0,8192):
data += '1'
client.sendall(bytes(data))
这是我使用的 tcpdump cmd:
sudo tcpdump -i lo 端口 10086 -s 1514 -v
从代码看,buf是8192,MSS是1460。所以,在我看来,数据包会被分成1460、1460、1460、1460、1460、892。但在截图中不是。
另外,我不确定这是否是由 [DF] 标志引起的。prog使用python,所以内置sockopt [DF]设置为默认?天知道。
解决方案
众所周知,MTU是1500,TCP的MSS是1460
这不是真的。
MTU 取决于传输介质,而 1500 的 MTU 特定于以太网。但是根据您的 tcpdump,您没有使用以太网接口(即两台机器之间的有线 LAN 连接),而是在同一台机器上拥有客户端和服务器,因此使用lo
接口 ( tcpdump -i lo ...
)。localhost 接口的 MTU 通常要高得多:
$ ifconfig lo
lo: ... mtu 65536
$ ifconfig eth0
eth0: ... mtu 1500
除此之外,您可能根本看不到任何碎片。如果数据包大于 MTU,您将看到 TCP 分段(不是分段),即操作系统会将 TCP 流分成不同的分段,每个分段如果不大于 MSS。相反,碎片发生在较低层,例如,如果 IP 数据包需要进一步拆分,因为到目标的路径中的某处是具有较小 MTU 的设备。
您看到的[DF]
(不要分段)是为了确保不会发生 IP 级别分段,而是丢弃数据包并通知发送方,以便可以发现路径 MTU(路径的最小 MTU)并优化 TCP 分段这是为了减少交付的开销。有关详细信息,请参阅路径 MTU 发现。