《计算机网络》读书笔记,主要介绍内容包括:TCP首部、流量控制、拥塞控制、TCP传输的连接管理
传输层有两种协议
- TCP (传输控制协议) 提供面向连接的、可靠的数据传输服务,数据传输的单位为报文段
- UDP(用户数据报协议) 提供无连接的、尽最大努力的数据传输服务,数据传输的单位是用户数据报
TCP协议的用途更广并且比较复杂,所以本文重点讨论TCP协议,内容包块
- TCP首部
- 流量控制
- 拥塞控制
- 慢开始算法
- 拥塞避免算法
- 快重传算法
- 快恢复算法
- TCP传输的连接管理
- TCP的连接建立
- 为什么是三次握手
- TCP连接释放
- TCP的保活计时器
1、TCP首部
TCP报文首部格式示例图:

源端口和目的端口
各占两个字节,TCP的分用功能也是通过端口实现的,一个有多个应用程序建立TCP连接,使用不同的端口号区分TCP属于那个应用程序
序号
占4个字节。序号范围是[0, 2^32 - 1],共2^32个序列号。序号达到最大值后,会从0重新开始。在一个TCP链接中传送的字节流中的每一个字节都按顺序编号。整个要传送的字节流的其实序号必须在连接建立时设置。首部中的序号字段值指的是本报文所发送的数据的第一个字节的序号。
确认号
占4个字节 是期望收到对方下一个报文段的第一个数据字节的序号。例如B收到A的序号为501、长度为200的报文段,B期望收到A的下一个数据序号是701,B发送给A的确认好需要设置为701。
数据偏移
占4位 TCP报文数据段距离TCP报文起始处的偏移位置,也就是TCP报文首部的长度。数据偏移的单位是32位字(4字节)。由于4位二进制数能表示的最大的十进制数字是15,因此数据偏移的最大值是60字节(4字节*15=60字节),也是TCP首部的最大长度,所以选项的最大长度为40字节。
控制位-紧急URG(URGent)
告诉系统此报文段中有紧急数据,应尽快传送(相当于优先级高的数据),URG设置为1时,发送方的TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。
控制位-确认ACK(ACKnowlegment)
确认控制位ACK为1时确认号才有效,TCP规定奖励链接之后的ACK控制位都需要为1
控制位-推送PSH(Push)
TCP的一端APP希望在键入一个命令之后对方能收到响应。在这种情况下,TCP就可以使用推送操作。接收方TCP收到PSH=1的报文段,就尽快的把数据提交给上层的应用,而不再等到整个缓存都填满了后再向上提交。
控制位-复位RST(Reset)
RST=1 表示TCP链接中出现了严重差错,必须释放链接,然后重新建立连接。RST=1还用来拒绝一个非法的报文或拒绝打开一个连接。
控制位-同步SYN(Synchronization)
连接建立时用来同步序号。当SYN=1并且ACK=0时表示这是一个连接请求报文。对方若同意建立连接,则响应的报文段中使用SYN=1和ACK=1.
控制位-终止FIN(Finish)
FIN=1时表示发送方的数据已经发送完毕,要求释放连接。
窗口
占2字节。窗口值是[0, 2^16-1]之间的整数。窗口指的是发送本报文段的一方的接收窗口,告诉对方允许发送的最大数据量。之所以要设置该值,是因为接收方的数据缓存空间是有限的,窗口值做饭接收方让发送方设置器发送窗口的依据。
检验和
占2个字节。检验和字段检验的范围包括首部和数据这两部分。和UDP用户数据报一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。
伪首部示例图:

伪首部:这种首部并不是真正的UDP用户数据报或者TCP数据报的首部。只是在计算检验和时,临时添加到UDP或者TCP前面,得到一个临时的UDP用户数据报或者TCP数据报。伪首部既不向下传送也不向上递交,而仅仅是为了计算检验和。
紧急指针
占2字节。紧急指针当且仅当在控制位URG=1时有效,它指出本报文中紧急数据的字节数(紧急数据结束之后就是普通数据)。当所有的紧急数据处理完时,TCP就告诉应用程序恢复到正常的操。另外在窗口为0时也可发送紧急数据。
2、流量控制
流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收,TCP连接的流量控制是通过滑动窗口协议实现的。
流量控制示例图:

流量控制步骤:
- A初始的发送窗口为400
- A发送了序号1-100的数据,发送窗口变成300
- A发送了序号101-200的数据,发送窗口变成200
- A发送了序号201-300的数据(该数据超时,会超时重传),发送窗口变成100
- B收到A的序号101-200的数据,发送确认信息,ack=201,rwnd=300,告诉A可以发送序号201-500共300长度的数据
- A收到B的确认信息,发送窗口变成200
- A发送了序号301-400的数据,发送窗口变成100
- A发送了序号401-500的数据,发送窗口变成0,不能再发送数据
- A发送了序号201-300的数据(重传计时器超时重传)
- B收到序号401-500的数据,发送确认信息,ack=501,rwnd=100,告诉A可以发送序号501-600共100长度的数据
- A收到B的确认信息,发送窗口变成100
- A发送了序号501-600的数据,发送窗口变成0,不能再发送数据
3、拥塞控制
网络中的带宽、交换节点中的缓存和处理机等都是网络资源。网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种情况叫做拥塞(congestion)。
3.1、几种拥塞控制的方法
拥塞控制有四种算法:慢开始(slow-start)、拥塞避免(congestion avoidance)、快重传(fast retransmit)、快恢复(fast recovery)
3.2、慢开始和拥塞避免
发送方维持一个拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态变化着。发送发的发送窗口等于拥塞窗口,如果考虑到接收方的接收能力,那么发送窗口还可能小于拥塞窗口。
发送方控制拥塞窗口的原则是:只要网络没有拥塞,窗口就增大一些,以便把更多分组发送出去,遇到网络拥塞,窗口减小一些,减少发送的分组。
而判定网络拥塞的方法是根据发送方有没有按时收到接收方的确认报文,没有按时收到确认报文有可能是丢包了,而这种情况的概率比较小,所以影响不大。
3.3、慢开始算法
慢开始的示例图,cwnd(congestion window 拥塞窗口):

慢开始的解释
- 开始发送方设置cwnd=1,发送1个报文段(M1),接收方收到返回确认
- 发送方增加cwnd=2,可以发送2个报文段(M2-M3),接收方收到返回确认
- 发送方增加cwnd=4,可以发送4个报文段(M4-M7),接收方收到返回确认
- 发送方增加cwnd=8,可以发送8个报文段(M8-M15)
每经过一个传输轮次,拥塞窗口cwnd就加倍,cwnd不能无限增大,有个最大值称为慢开始门限ssthresh,用法如下:
- cwnd<ssthresh,使用慢开始算法
- cwnd>ssthresh,使用拥塞避免算法
- cwnd=ssthresh,使用慢开始算法或者拥塞避免算法
3.4、拥塞避免算法
cwnd>ssthresh,使用拥塞避免算法,拥塞避免算法的思路是让cwnd窗口缓慢增大,没经过一个RTT就把cwnd增加1,而不是加倍,cwnd是线性增长的。
3.5、慢开始和拥塞避免的协作
不管是慢开始还是拥塞避免阶段,如果遇到网络阻塞,慢开始门限ssthresh值都会减半,并且cwnd重置为1,重新执行慢开始算法。
慢开始算法和拥塞避免算法示例图:

3.6、快重传算法
快重传算法首先要求接收方每收到一个失序的报文段后就立即发出重复确认,之所以如此是因为为了让发送方及早知道有报文段没有到达对方。
快重传示例图:

快重传示步骤解析:
- 接收方收到数据M1和M2并且发送确认
- 接收方收到M4,属于失序数据,因为没有收到M3,按照快重传的规定,要发送M2数据的重复确认
- 接收方收到M5和M6也一样要发送M2数据的重复确认
- 接收方一共收到三个重复确认立即重传未收到的报文段M3,而不必等待为M3设置的重传计时器到期
3.7、快恢复算法
当发送方连续收到3个重复确认时,把慢开始门限ssthresh减半,而接下来不是执行慢开始算法,因为此时很可能没有网络阻塞发生,如果发生了阻塞就不会有连续的重复确认报文段了。转而执行快恢复算法,把拥塞窗口cwnd设置为ssthresh减半之后的值,然后开始拥塞避免算法。
快恢复的示例图(TCP reno版本这条曲线):

3.8、拥塞窗口、对方接收窗口、发送窗口之间的关系
因为发送窗口总是要小于对方接收窗口,发送数据接收方才能来得及处理,所有有以下公式:
发送窗口=MIN(拥塞窗口, 对方接收窗口)
4、TCP传输的连接管理
4.1、TCP的连接建立
TCP 连接建立的三次握手步骤示例图:

具体的步骤:
- B服务器的TCP进程先创建传输控制块TCB,准备接受客户端进程的连接请求。B服务器处于LISTEN(监听)状态,等待客户端的连接请求。
- A客户端进程创建传输控制块TCB,然后向B服务器发出连接请求报文段,这时首部中的同部位SYN=1,同时选择一个初始序列号seq=x。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但要消耗一个序号。这时A客户端进入了SYN-SEND(同步发送)状态。
- B服务器收到A客户端的连接请求报文段后,确认建立连接需要设置SYN=1、ACK=1,选择一个储蓄的序列号y,发送确认号ack=x+1(根据TCP确认号的规定,A客户端发送的上一个报文的序号是x,没有数据但是要消耗一个字节,所以ack=x+1,告诉A客户端发送的下一个数据的序号是x+1),B此时进入SYN-RCVD(同步收到)状态。
- A客户端还需要向B服务器给出确认。确认控制位ACK=1,序号seq=x+1,确认号ack=y+1,A客户端进入了ESTABLISHED(连接建立)状态
- B服务器收到A的确认之后,也进入了ESTABLISHED(连接建立)状态
4.2、为什么是三次握手
三次握手是为了防止A客户端向B服务器请求资源,一个请求可能因为网络原因到没有准时达到B服务器,导致A客户端建立多个TCP握手连接。考虑以下两种情形
-
1)、A客户端发送的请求因为网络原因被丢弃了,这种情况B不会收到,B不会建立连接,直到A重新发送连接请求收到了之后才能建立连接。
-
2)、A客户端发送的请求因为网络原因在网络中的某个节点停留时间过长而超时(第一个数据包假设为P1),导致A客户端重新发送建立连接请求(第二个数据包假设为P2),B服务器收到了P1,如果只有两次握手,B服务器会建立了连接一直等待A客户端,导致了资源的浪费,有了三次握手,B服务器会发送确认信息到A客户端,A客户端未发送信息给B服务器,B服务器判定该连接是无效的连接,不建立连接。
第(1)种情况是并不会产生问题,第(2)种情况的两次握手会产生问题,所以需要三次握手
4.3、TCP连接释放
TCP连接释放示例图:

具体的步骤:
- A客户端发送FIN=1的报文,序号seq=u是最后一个发送数据字节序号+1,A客户端进入了FIN-WAIT1(终止等待阶段1)状态FIN-WAIT1(终止等待阶段1)状态
- B服务器收到A的报文段,发送确认包ACK=1,序号seq=v是最后一个发送数据字节序号+1,确认码ack=u+1,B服务器进入CLOSE-WAIT(关闭等待)状态
- 此时A客户端到B服务器的数据通道已经关闭,如果此时B服务器到A客户端仍然有数据,B服务器可以继续发送,A客户端需要接收,数据发送完成之后,B服务器发送一个确认终止的数据包FIN=1,ACK=1,序号seq=w是最后一个发送数据字节序号+1,确认码还是和上一个数据报的一样ack=u+1,B服务器进入LAST-ACK(最后确认)状态
- A客户端收到B服务器的数据包,发送确认数据包ACK=1,seq=u+1,ack=w+1,A客户端进入TIME-WAIT(时间等待)状态
- B服务器收到A客户端的数据包,进入到CLOSE(链接关闭)状态
- A客户端需要经过时间等待计时器设置的2倍MSL(Maximum Segment Lifetime 最长报文寿命),才能进入到CLOSE状态,之所以要设置2倍的MSL等待时间是因为有可能B服务器没有收到A客户端的确认报文不能正常关闭TCP连接,B服务器没有收到A客户端的确认报文会重传(FIN ACK)报文段,A客户端会在2MSL时间内发送确认包,B收到了确认包之后才能关闭TCP连接,然后A客户端关闭TCP连接,A客户端关闭TCP连接的时间会稍微晚于B服务器关闭TCP连接的时间。
4.4、TCP的保活计时器
存在客户端和服务器在建立连接中途客户端发生故障的情况,服务器之后接收不到客户端的数据包。服务器设置了保活计时器,服务器每收到一次客户端的连接,会重新设置保活计时器,一般是2个小时,如果计时器超时,服务器会每隔75分钟发送一个探测包,发送了10个之后没有收到响应,服务器会任务客户端出现了故障,关闭这个连接。
网友评论