什么是MSS&MTU以及发送窗口&滑动窗口

这两天接了西云的面试,还在准备状态,在这边重新拎一下TCP/IP吧。

在看一本Wireshark的书,可惜本人基础不牢,遇到一些问题还要继续搜寻答案。

  • 发送窗口和MSS有什么关系?
    • 发送窗口决定了一口气能发多少字节,而MSS决定了这些字节要分多少个包发完。举个例子,在发送窗口为16000字节的情况下,如果MSS是1000字节,那就需要发送16000/1000=16个包;而如果MSS等于8000,那要发送的包数就是16000/8000=2了。

从上面这个问题引出了我的几个问题,MSS是什么,听起来像是一个TCP的切片(不正确)。

1.什么是MSS

找到一篇赛博佛祖的文章,我觉得很棒:什么是 MSS(最大分段大小)?

里面有张图很灵魂,但是我为了迅速我就不贴了。

MSS的全程为maximum segment size,MSS 测量数据包的非标头部分,称为有效负载。MSS 是联网设备可以接收的最大 TCP(传输控制协议)段大小。MSS 将“段”定义为仅有效负载的长度,而不是任何附加的标头。MSS 以字节为单位。

从上面一段,我理解为,MSS是TCP协议的最大有效负载,一般为MTU - (TCP 标头 + IP 标头) = MSS 1460bytes。

TCP和IP标头一般为20bytes大小。由此可以总结,TCP包的长度为1480(包含了TCP头),IP包的长度为1500(包含了TCP和IP头)。

2.什么是MTU

其实有点自上往下的概念了,我个人认为MTU是以太网的最大传输负载。也就是默认缺省的1500bytes。

MTU是工作在IP层的概念,但是MTU为什么这么大就要看下面这段数据链路层的解析。

以太帧帧长最小为64bytes,最大为1518bytes,可以知道以太帧有效数据部分最最小为64-6-6-2-4 = 46bytes,最大为1518-6bytes目标MAC地址-6bytes源MAC地址-2bytes数据帧类型-4bytes校验 = 1500bytes,这个最大值就称为MTU,所以通常是1500bytes。

1
2
3
4
5
6
7
$ sudo netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
docker0 1500 0 0 0 0 0 0 0 0 BMU
eth0 1500 3612953 0 15 0 17609443 0 0 0 BMRU
lo 65536 530041 0 0 0 530041 0 0 0 LRU
tailscale0 1280 16860 0 0 0 16828 0 0 0 MOPRU

如上是我在我的树莓派上运行的命令结果,可以查看所有网络接口的MTU,可以看到除了loopback和tailscale其他的借口都是1500的MTU。

MTU 和 MSS 之间的主要区别之一是,如果数据包超过设备的 MTU,则会分解为更小的部分,或“分段”。相反,如果一个数据包超过 MSS,它就会被丢弃并且不会被传递。

这边是Cloudflare的文章:什么是MTU?

3.发送窗口&接收窗口

回到我们最开始的问题,发送窗口和MSS的区别,现在我们知道了MSS是TCP的最大有效负载,那么发送窗口这个东西就涉及到了拥塞控制以及接受窗口。

按照我的理解,发送窗口的概念无法直接从数据包中看到,并且发送窗口的大小也十分多变,在不考虑网路拥塞的情况下,发送窗口的大小我理解为接受窗口的大小,为了最大的传输效率,我们将接受窗口发满就停止发送。

但是考虑了网络拥塞情况之后,发送窗口的大小就变成了min{拥塞窗口,接收窗口}。

也就是如果网络拥塞的话,发送窗口的长度还会减少。

在TCP三次握手中会发送双方的接收窗口大小,包括TCP正常标头中也带有接收窗口大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Frame 6123: 66 bytes on wire (528 bits), 66 bytes captured (528 bits) on interface \Device\NPF_{09654748-C1E7-44D2-8609-0E144AA81F34}, id 0
Ethernet II, Src: Microsoft_1b:f9:ba (7c:1e:52:1b:f9:ba), Dst: 12:34:56:78:9a:bc (12:34:56:78:9a:bc)
Internet Protocol Version 4, Src: 10.0.0.4, Dst: 142.251.163.188
Transmission Control Protocol, Src Port: 52200, Dst Port: 5228, Seq: 0, Len: 0
Source Port: 52200
Destination Port: 5228
[Stream index: 22]
[Conversation completeness: Complete, WITH_DATA (31)]
[TCP Segment Len: 0]
Sequence Number: 0 (relative sequence number)
Sequence Number (raw): 219430569
[Next Sequence Number: 1 (relative sequence number)]
Acknowledgment Number: 0
Acknowledgment number (raw): 0
1000 .... = Header Length: 32 bytes (8)
Flags: 0x002 (SYN)
Window: 64240
[Calculated window size: 64240]
Checksum: 0x3ce2 [unverified]
[Checksum Status: Unverified]
Urgent Pointer: 0
Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted
TCP Option - Maximum segment size: 1460 bytes
TCP Option - No-Operation (NOP)
TCP Option - Window scale: 8 (multiply by 256)
Kind: Window Scale (3)
Length: 3
Shift count: 8
[Multiplier: 256]
TCP Option - No-Operation (NOP)
TCP Option - No-Operation (NOP)
TCP Option - SACK permitted
[Timestamps]

我们可以从上面的抓包信息中看到,Window: 64240,下面wireshark也给我们计算了实际的窗口大小,至于为什么数值一样是因为SYN包不放大。其计算方式为,下面的window scale字段的shift count值,如上数据2的8次方等于256,再将64240和256相乘便得到了实际的窗口值。

4.滑动窗口

滑动窗口就比较难解释了,以我的理解,所有等待发送的资源,都会发往缓冲区,发送窗口维护着四个概念:

  • 已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)
  • 已发送但未收到确认的数据(位于发送窗口中)
  • 允许发送但尚未发送的数据(位于发送窗口中)
  • 不允许发送的数据(不在发送窗口中但在发送缓冲区)
1
1 2 3 4 |->5 6 7 8 9 10 11 12<-|->13 14 15 16

如上所示的5-12可以理解为滑动窗口区域,1-4为已发送并且收到确认的数据,滑动窗口区域是允许发送的数据也就是发送窗口的大小,按照TCP建立连接后接收方的接收窗口大小一致(不拥塞的话)。

当发出的数据包收到确认的ack时,滑动窗口的左沿和右沿都会向前滑动。

当网络出现拥塞时,或者接收端的接收窗口为0时,滑动窗口的右沿则会左移,使滑动窗口减小即发送窗口减小。


什么是MSS&MTU以及发送窗口&滑动窗口
https://steammilk.com/2025/01/08/2025-all/mss/
作者
蒸奶泡
发布于
2025年1月8日
更新于
2025年1月8日
许可协议