Skip to content

Commit 6c4a8f1

Browse files
committed
update
1 parent 14b6d10 commit 6c4a8f1

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
* Computer Networking Top-Down Approach, 7th
44
* TCP/IP Illustrated Volume 1, 2nd
55
---
6-
- [x] Application Layer
7-
- [ ] Transport Layer
6+
- [x] [Application Layer](Application-Layer.md)
7+
- [ ] [Transport Layer](Transport-Layer.md)

Transport-Layer.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,62 @@
8484
2. TCP的一条连接由一个四元组(src_ip, src port, dst_ip, dst_port)标识,当处于`TIME_WAIT`时,此条连接会被定义为不可使用,这样就避免了一条连接关闭后能立即生成同一条连接,接收到上一次连接的分组。
8585

8686
**避免TIME_WAIT**
87-
`SO_REUSEADDR`这个套接字选项允许分配处于`TIME_WAIT`的端口来建立TCP连接。这一点违背了TCP的最初规范,但是只要能保证不会收到上一条连接分组的干扰,就可以使用。
87+
`SO_REUSEADDR`这个套接字选项允许分配处于`TIME_WAIT`的端口来建立TCP连接。这一点违背了TCP的最初规范,但是只要能保证不会收到上一条连接分组的干扰,就可以使用。
88+
89+
## 超时重传
90+
TCP超时重传的基础就是需要根据RTT(Round-Trip Time)分组往返时间设置RTO(Retransmission Timeout)超时重传时间。
91+
上述过程有以下方法:
92+
* 经典方法
93+
SRTT = a(SRTT) + (1-a)RTT,其中a取0.8-0.9,SRTT为平滑RTT估计值,RTT为新测的一个RTT样本。得到新的SRTT后,RTO = min(ubound, max(lbound, (SRTT)b)),其中ubound是RTO的上边界,lbound为RTO下边界,b为时延离散因子,通常为1.3-2.0。
94+
此方法在RTT波动较大的网络中,效果很差。
95+
* 标准方法
96+
基于平滑RTT和平滑偏差计算
97+
(平滑RTT)srtt = (1-g)srtt + gM
98+
(平滑偏差)rttvar = (1-h)rttvar + h(|M-srttt|)
99+
RTO = srtt + 4rttvar
100+
101+
## 快速重传
102+
根据收到冗余的ACK来判断是否发生丢包,通常冗余ACK的数量有个阈值dupthresh(常量3),到这个值时,大概率产生丢包,发生重传。
103+
104+
## 重传二义性和karn算法
105+
* 当重传了一个数据包后,收到一个确认,该确认可能是第一次传输的确认也可能是重传的确认。
106+
* 很明显根据此确认计算RTT可能不是准确的,所以karn算法第一部分规定,接收重传的确认时,不更新RTT估计值。
107+
* 每重传一次,计算RTO的退避系数加倍,这是karn算法的第二部分。
108+
109+
# 数据流与窗口管理
110+
111+
## 延时确认
112+
大多数情况下,TCP不会为每个受到的数据包返回一个ACK,而是累计收到多个后,返回一次ACK,但是为了避免引发重传,延时理论值最高为500ms,实际中最大取的是200ms。
113+
114+
## Nagle算法
115+
为了减少网络中微型包的数量,引入了nagle算法。
116+
* 一个TCP连接中只允许有一个小于MSS的报文段在传输,在该报文段的ACK到达之后,TCP会收集小数据并整合为在一个报文段中再发送。
117+
118+
### 延时ACK和Nagle算法
119+
若两者结合使用,结果可能会很不理想。比如说客户端使用延时ACK,服务端使用nagle算法,当服务端发送了一个小包后,会一直等这个包的ACK,而客户端接收到这个小包后进入延时ACK的计时器,希望有新的数据包捎带此ACK回复给服务端,这样两者会互相等待对方,造成暂时性死锁。
120+
**禁用nagle**:设置TCP_NODELAY选项。
121+
122+
## 滑动窗口和接收窗口
123+
### 滑动窗口
124+
![](pics/滑动窗口.png)
125+
1. 关闭:窗口左边界右移。当已发送的数据收到ACK时,窗口会减小。
126+
2. 打开:窗口右边界右移。当已确认数据的到处理,窗口会变大。
127+
3. 收缩:窗口右边界左移。
128+
129+
### 接收窗口
130+
![](pics/接收窗口.png)
131+
到达的序列号小于RCV.NXT或大于RCV.NXT+RCN.WND则丢弃。只有序列号等于RCV.NXT时,窗口才会向右移动,但是设置了SACK选项后,也可以确认窗口内的其他报文段(乱序包),直到收到序号等于RCV.NXT的包,窗口才会向右滑动。
132+
133+
### 零窗口和持续计时器
134+
当接收端的窗口值变为0时,会通知给发送端,直到应用程序处理数据,窗口重新获得可用空间时,会给发送端发一个窗口更新(一个纯ACK),不保证传输可靠,所以如果丢失,双方都会等待,发送方等待窗口更新,接收方等待接收数据。为了避免此死锁发生,TCP引入了 **持续计时器**
135+
* 当发送端收到零窗口通告时,会开启持续计数器,间歇性的发送窗口探测,强制要求接收端回复一个ACK(包含了窗口大小)查询接收端的窗口是否增长。一般在第一个RTO后发送第一个窗口探测,随后采用指数规避发送窗口探测。
136+
137+
### 糊涂窗口综合征(silly window syndrome)
138+
发生该问题的时候,TCP交换的不是全长包,而是一些小包,小包传输代价相对大,传输效率很低。
139+
出现原因:
140+
* 接收端通告窗口太小
141+
* 发送端发送的数据较小
142+
143+
应对:
144+
* 接收端:窗口增至可以放下一个全长报文段,或者接收端缓存的一半(两者中较小者)的时候才能开始发送新窗口通告。
145+
* 发送端:1.可以发送一个全长报文段 2.可以发送数据段长度 >= 接收端通告过的最大窗口值的一半的报文段 3.当禁用了Nagle算法或者所有发出的数据都已经被对端ACK确认的话,那么TCP可以发送小数据包

0 commit comments

Comments
 (0)