【计算机网络】传输层协议TCP

时间:2020-12-11 14:34:54

TCP协议概述


TCP是面向连接的,面向字节流的传输层协议,每一条连接只能有两个端点,是点对点的。它能提供可靠的传输服务,属于全双工通信。一个TCP报文段的首部格式如下:
【计算机网络】传输层协议TCP
首部各字段的意义:
1>源端口和目的端口:通讯的双⽅由IP地址和端口号标识。
2>序号:在一个TCP连接中传送的字节流的每一个字节都需要按顺序编号,若当前序号为120,携带数据100字节,那么下一个报文段就必须从220开始。
3>确认序号:期望收到对方下一个报文的序号,如果是221,说明到序号为200的数据都正确收到了。
4>数据偏移:其实就是首部长度。在交付给上层时需要去除首部,就必须知道首部的长度。
5>保留:保留给今后使用。
6>紧急URG:值为1时,紧急指针有效,数据不再排队传送。直接插入到本报文段数据的最前面,但是紧急数据后面的数据仍是普通数据。
7>确认ACK:ACK=1时,确认序号字段有效。为0时无效,说明该段报文只是单纯的传输,并不会捎带确认。
8>推送PSH:PSH=1时,将这个报文及缓存区之间缓存尚未交付的数据一并交付给进程。
9>复位RST:RST=1时,TCP连接出现严重错误需要重新连接或者拒绝一个非法的报文段。
10>同步SYN:SYN=1时说明这是一条请求连接或者接受连接的报文。
11>终止FIN:FIN=1时,说明这是一条请求释放连接的报文。
12>窗口:窗口是用来告诉对端,当前自身的接收能力是多大。
13>检验和:用来检测数据正确性。检验的范围包括首部和数据两部分。
14>紧急指针:和URG配合使用。指出紧急数据的字节数。
15>选项:可变长
TCP属于IP的上层协议,所以,它封装在IP的数据部分。

字段URG和PSH都是用来标识紧急数据的,它们有什么区别呢?
1、URG紧急位
URG=1,该tcp报文为紧急报文;其中的紧急数据需要直接交付给接收端的进程,而不进入缓存。
紧急数据的长度=紧急指针;
紧急数据的起始点=序号;
紧急数据的终止点=序号+紧急指针;
(综上,紧急指针就是记录紧急数据的字节数,紧急指针永远为正数)
1)在紧急数据后面的数据为普通数据,需要按序缓存。
2)窗口为0也可以发送紧急数据。
3)紧急数据都处理完成后,tcp就告诉进程恢复到正常操作。

2、PSH推送位
PSH=1,该报文希望,到达对端时,将这个报文及缓存区之间缓存尚未交付的数据一并交付给进程。
1)PSH的数据=本报文数据+缓存区数据
2)PSH的方向—>单方向(接收PSH报文的一端)

3、区别
URG交付给进程的数据:只有紧急数据
PSH交付给进程的数据:缓冲区排好序的数据及当前报文中的数据


TCP连接建立过程


【计算机网络】传输层协议TCP
连接建立过程时的状态基如上图,我们分析一下这个过程。
1.起初,A,B都处于CLOSED(关闭)状态。
2.主机A主动打开连接,服务器B被动打开连接。B创建TCB(维护连接的数据结构),进入LISTEN状态。
3.A也需要创建TCB,然后向B发送请求连接报文,自己进入SYN-SEND(同步已发送状态)。
4.B收到报文后向A发送确认,自己进入SYN-RCVD(同步收到)。
5.A收到B的确认后,需要再向A给出确认,然后进入ESTAB-LISHED(已建立连接)。
6.B收到A的确认后,也进入ESTAB-LISHED。

那么,TCP连接为什么要三次握手呢
考虑假如只有两次握手会出现的情况:
A向B发送了一次连接请求,但是此报文在网络中滞留了很久(对于A来说已经失效),但是B收到后对报文进行了确认,但是A此时没有发送确认报文,所以不会理财B的确认。上面也提到过,服务器B会建立一套用来维护连接的数据结构TCB,那么这种情况下B认为连接已经建立,会一直等待A发送数据,浪费了资源。

或者A恶意的攻击服务器B,疯狂的发送连接请求给B,如果只有两次握手,B确认后就认为连接建立了。最终会导致服务器瘫痪。

所以两次肯定是不行的,那四次、五次、更多次呢?当然不会出现上述安全的问题,但是既然3次可以做到,那次数多了除了浪费时间也没啥好处,所以,TCP连接需要三次握手。


TCP连接释放过程


【计算机网络】传输层协议TCP
连接释放过程(四次挥手)及双方状态改变如上图。
数据传输结束后,双方都可以释放连接。
1.A向B发送释放连接请求,并停止发送数据,主动关闭TCP连接。自己进入FIN-WAIT-1(终止等待1)状态。
2.B收到后发送确认,进入CLOSE-WAIT(关闭等待)状态,此时TCP处于半关闭状态,因为,虽然A不会再给B发送数据了,但是B可能会有数据要发送给A。
3.B一段时间后也没有数据要发送了,向A发送释放连接请求,发送后B进入LAST-ACK(最后确认)状态。
4.A收到B的释放连接请求报文,必须再向B发送此报文的确认报文,然后A进入TIME-WAIT(时间等待)状态。等待2MSL后,A才能进入CLOSED状态。
5.B在收到A的最后确认后,直接进入CLOSED状态。

A在发送完最后一条报文后,为什么还要等待2MSL后才能进入CLOSED状态呢?
第一,为了保证 A 发送的最后一个 ACK 报文段能够到达B。

万一A的最后一个ACK报文段丢了,那么A在等待的时间里就可能再次收到B的释放连接请求,此时A就知道它发送的上一条报文丢了,它会重发。如果不等待,那当最后一条确认报文丢了之后,B就不会进入CLOSED状态。

第二,防止 “已失效的连接请求报文段”出现在本连接中。A 在发送最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续产生的报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。

这里的2MSL叫做时间等待计时器,TCP中有四种计时器,我们来一个个认识一下。

一、时间等待计时器
时间等待计时器是在连接终止期间使用的 。当TCP关闭一个连接时,它并不认为这个连接马上就真正地关闭了。在时间等待期间中,连接还处于一种中间过渡状态。这个计时器的值通常设置为一个报文段的寿命期值的两倍 。
二、保活计时器
实际上,服务器每收到一个客户机的报文后都会重设保活计时器(2小时),因为客户机有可能在建立连接后由于某些原因出现故障,没来得及释放与服务器的连接,所以这个保活计时器就是为了避免服务器一直等下去。若超过这个计时器的时间服务器还没有收到客户机的数据,就会发送一个探测报文,以后每隔75分钟发送一次,若连续10个探测报文都没有得到客户机的响应,服务器则认为客户机故障,然后关闭连接。
三、重传计时器
当TCP发送报文段时,就创建该特定报文段的重传计时器 。可能发生两种情况:
(1)、若在计时器截止时间到( 通常是60秒 )之前收到了对此特定报文段的确认,则撤销此计时器。
(2)、若在收到了对此特定报文段的确认之前计时器截止期到,则重传此报文段,并将计时器复位。
四、坚持计数器
为了对付零窗口大小通知,TCP需要另一个计时器。假定接收TCP宣布了窗口大小为零。发送TCP就停止传送报文段,直到接收TCP发送确认并宣布一个非零的窗口大小。但这个确认可能会丢失。我们知道在TCP中,对确认是不需要发送确认的。若确认丢失了,接收TCP并不知道,而是会认为它已经完成任务了,并等待着发送TCP接着会发送更多的报文段。但发送TCP由于没有收到确认,就等待对方发送确认来通知窗口的大小。双方的TCP都在永远地等待着对方。
要打开这种死锁,TCP为每一个连接使用一个坚持计时器。 当发送TCP收到一个窗口大小为零的确认时,就启动坚持计时器 。 当坚持计时器期限到时,发送TCP就发送一个探测报文段 。这个报文段只有一个字节的数据。它有一个序号,但它的序号永远不需要确认;甚至在计算对其他部分的数据的确认时该序号也被忽略。探测报文段提醒对端:确认已丢失,必须重传。
坚持计时器的值设置为重传时间的数值。但是,若没有收到从接收端来的响应,则需发送另一个探测报文段,并将坚持计时器的值加倍和复位。发送端继续发送探测报文段,将坚持计时器设定的值加倍和复位,直到这个值增大到门限值( 通常是60秒 )为止。在这以后,发送端每隔60秒就发送一个探测报文段,直到窗口重新打开。