由于面试中经常会问到TCP协议的一些细节,比如三次握手的详细过程、断开连接的过程、滑动窗口、拥塞控制等方面的内容,因此这里就整理下。
一.传输层协议
传输层主要是包含两个协议,即TCP和UDP协议。
UDP (User Datagram Protocol):基于UDP协议的上层协议包括 DNS,RIP,DHCP,NFS等。传送数据前不需要先建立连接。
TCP (Transmission Control Protocol):基于TCP协议的上层协议包括SMTP,Telnet,HTTP,FTP等。TCP是面向连接的。
由于传输层使用IP+端口号使得不同主机上的进程可以通信,也就是Socket,如192.168.1.1:8080。端口号是16位,最大为65535。其中,0-1023是保留端口号,如常见的有FTP 21, Telnet 23,SMTP 25, DNS 53, HTTP 80等。
二.UDP协议简介
UDP协议非常的简单,仅仅在IP协议上增加了一点点功能。主要特点是:
- 无连接。
- 尽最大努力交付。
- 面向报文。对应用层交下来报文不拆分也不合并,直接添加首部交给IP层。因此若报文太长,就会让IP传输很长时间,若报文太短,会使得大量空间浪费在各类协议首部,降低传输效率。
- 支持1对1,1对多,多对多。
- 没有拥塞控制。
- 报文首部开小,只有8个字节。包含源端口号、目的端口号、长度和校验和。
三. TCP概述
TCP协议的特点是:
- 面向连接
- 点对点(一对一)
- 可靠交付
- 面向字节流,也就是说仅仅把上层协议传递过来的数据当成字节传输。
为了实现TCP上述的特点,TCP协议需要解决的是面向连接(建立连接和关闭连接的方式)、可靠传输(错误确认和重传)、流量控制(发送方和接收方的传输速率协调)、拥塞控制四个方面。
四 TCP协议首部格式
TCP协议首部最小长度是20字节,首部有一个长度可变的选项部分,最大40字节,所以TCP首部长度是20-60字节大小。具体如图:
选取部分字段说明:
序号:TCP传输的时候每一个字节都按顺序编号;协议中的序号是本报文段所发送数据第一个字节的序号。序号也用于建立和结束连接时候使用。
确认号:用于可靠传输中,返回确认报文序号。
数据偏移:指出数据段在报文中开始的位置。
窗口:可靠连接和流量控制中所用到的窗口大小。
上图中有六个控制位,对于建立和结束连接非常关键,解释如下:
- URG(Urgent):紧急字段,可以让该报文不按报文顺序优先被处理。比如用户突然终止传输关闭连接。
- ACK(Acknowledge):所有建立连接后传送的报文ACK必须为1.
- PSH(Push):发送方讲该报文推送向前,可以不用等缓存填满先提交给应用程序。
- RST(Reset):连接出现严重差错时候设为1,重新建立连接。也可用于拒绝建立连接。
- SYN(Synchronize):建立连接时候的同步标志。SYN=1而ACK=0时表示建立连接请求。
- FIN(Finish):终止时标志位。
另外,在选项中有这么几种选择:
- 最大报文长度MSS(Maxium Segment Size),指的是一个TCP报文数据段的最大长度。要尽可能大一些但是又不需要IP拆分。推荐是536字节,这样真个TCP报文长度是 536+20 = 556字节。
- 窗口扩大选项。可用于控制传输窗口大小。
- 时间戳。非常有用。可以用于 1)计算往返时间RTT 2)区分重复报文。因为报文的序号只能是2^32-1个,所以很容易就重复了,加上时间戳可以进行区分。
五 TCP协议的建立连接过程(三次握手)
著名的三次握手协议,一图胜万语。
对上图的说明:
SYN和ACK已经说过了。seq就是首部中的序号字段,图中x和y都是随机生成的,然后收到后返回确认会将其+1.注意发送方和接收方的状态变化如下:
发送方: CLOSED-->SYN-SENT-->ESTABLISHED
接收方: CLOSED-->LISTEN-->SYN_RECEIVED-->ESTABLISHED
为什么需要三次握手?主要是为了防止“已失效的连接请求”。加入只要两次握手,即A发送请求B返回确认就可以建立连接。可能会出现以下情况:比如,A发送的第一个连接请求并未丢失,而是延滞了,此时A已经放弃了建立连接,但是B又最终收到了,于是返回ACK给A,这样就错误的建立了连接。
六 TCP协议关闭连接过程(四次握手)
释放连接的过程也见下图:
对上图的说明:FIN、ACK字段之前已经讲过。seq是序列号,图中每一个新的字母都表示随机生成。释放连接的状态变化:
发送方:ESTABLISHED-->FIN-WAIT_1-->FIN-WAIT_2-->TIME-WAIT-->CLOSED
接收方:ESTABLISHED-->CLOSE-->WAIT-->LAST-ACT-->CLOSED
注意,释放连接包含两个来回。前两次握手代表发送方不再传输数据了。后两次握手代表接收方不再传输数据了,因为TCP是全双工通信,二者是可以同时发送消息和接受消息的。所以图中B的CLOSE-WAIT阶段,仍然可以传输数据。
为什么A在发送确认后还有TIME-WAIT的阶段?有两个理由:
- A发送的最后一个ACK必须到达B。如果B没有收到该ACK,可能会再次发送FIN+ACK。如果此时A关闭了,B就不可能收到ACK了,也就无法正常关闭。
- 同三次握手一样,A等待一段时间,可以上网络中本次连接的延滞的请求都发送到位,然后再关闭连接,这样网络里面就不会再剩下本次连接的请求了。
TIME-WAIT设置为多久?更具上述分析,一般会把TIME-WAIT时间设置为2MSL,MSL代表最长报文寿命(Maximum Segment Lifetime)。也就是说,如果一段报文最长寿命为2分钟,会让A等待4分钟后再关闭。
七 TCP协议可靠传输的实现
基本原理
考虑A发送数据到B接受的情况。记报文为M。
停止等待协议:A每发送完一个报文M,就等候B对其确认;收到确认后继续发送。A设置超时重传机制。因此这种机制也成为自动重传请求ARQ(Automatic Repeat reQuest)。连续ARQ协议/窗口滑动协议
显然,每次只发送一个报文然后等待确认效率太低。所以可以约定每次发送多个报文,然后采用累积确认的方式。B对按序到达的最后一个分组发送确认。如果中间发生丢失包的情况,A需要回退到确认的报文重新发送。如图所示。
说明一下:A的发送窗口大小是根据B接受窗口设置的。也就是说A发送的报文速度不能超过B处理报文的速度。
TCP中对于超时重传时间的选择是根据平均往返时间RTT来计算的。也就是说,如果A超过一个报文平均往返时间没有收到确认,就会重新发送报文。
八 TCP协议流量控制
流量控制,简单来说就是不能发送的太快,以免处理不完,也不能发送的太慢,以免浪费资源。TCP协议中,建立连接之时,B会告诉A自己接受窗口的大小,A的窗口大小不会超过这个大小。
传输过程中,B会根据自己数据缓存的情况给A返回自己的窗口大小,例如,刚开始发送数据时,B的缓冲区为空,设置窗口大小为300,A开始发送;但是由于A发送的太快,B缓冲区渐渐变满,就会将接受窗口的大小设为100;如果B的缓冲区满了,还可能将窗口大小设为0,A就停止发送,直到B重新发送了一个窗口大小。
九 TCP协议拥塞控制
慢开始、拥塞避免、快重传、快恢复
拥塞控制发生在网络中负载太大,比如路由器IP包队列堆满了,就会丢弃尾部的包,从而导致TCP层数据的丢失。拥塞控制就是要避免网络数据量太大导致传输效率、速度降低。
常见的TCP拥塞控制方法包括四种:
- 慢开始
- 拥塞避免
- 快重传
- 快恢复
慢开始是指,TCP开始建立连接发送数据后,每次发送的报文段数从1开始。不能一开始就发送大量的报文段。如果网络畅通,发送方每个数据往返来回就把发送报文的数据量增加一倍。注意,这里的报文数据量指的就是窗口大小。
这样指数级会导致发送窗口快速增长。当超过一定值时候,就可能导致网络拥塞了,这个值被称为慢开始门限ssthresh。超过ssthresh后就采取拥塞避免的算法。变为发送窗口每次增长1.
如果A超过一定时间没有收到B发来的确认,说明报文丢失了,网络拥塞出现,此时将窗口大小设置为1,并将ssthresh设置为出现拥塞时窗口大小的一半。重新进行慢开始算法。这个过程称为AIMD(加法增大乘法减小)。
快重传是指,接收方B每收到一个失序的报文段(以为之前有报文段拥塞了)就立即发出重复确认。发送方如果连续收到三个重复确认就立即重传该报文段,而无需等候为重传计时器。如下图:
快重传和快恢复配合使用。如果发送方连续收到三次重复确认时,就执行“乘法减小”策略。但是不同之处在于,此时不再将窗口设置为1(慢开始算法),而是执行拥塞避免算法。如下图:
增加了拥塞控制算法后,TCP协议中发送方窗口大小设置为:
Min[拥塞窗口,接收方窗口]
随机早期检测RED
对TCP拥塞控制影响最大的是路由器的分组丢弃策略。路由器按照先进先出的原则发包。当队列满了之后,就会将超出队列的包一起丢弃。
由于一个路由器的包是来自于不同TCP协议客户端,这些发送方会同时发现丢包了,于是执行拥塞算法,此时网络中流量骤然下降,待网络恢复后,通信量又会突然增大。
为了避免这种情况出现,可以让路游戏采用随机早期检测算法RED(Random Early Detection)。方法很简单,设定一个队列最小阈限THmin和队列最大阈限THmax。当队列长度
参考文献
《计算机网络(第五版)》谢希仁,文中所有内容和配图均来自本书第五章