计算机网络学习随笔记(TCP协议)

    技术2022-07-12  71

    TCP协议:

    TCP协议认为网络环境是恶劣的,丢包、乱序、重传、拥塞都是常有的事情,一言不合就可能送达不了,所以从算法层面来保证可靠性。

    TCP包头格式如下图:

    源端口号跟目标端口号是必不可少的,它们标识着数据包应该发送给哪一个应用。

    序包是为了解决乱序的问题,确认序号是标识对方接收到了这个包。

    状态位SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束连接。

    窗口大小是TCP用来做流量控制的,通信双方都会声明一个窗口标识自己能接收数据包的大小,防止发生过多数据包或过少数据包。

    TCP的三次握手:

    TCP三次握手主要是为了双方能够确认对方能够接收到自己发生出去的信息。假如现在A要与B进行连接,A就会发送一个信息给B,B接收到信息后就返回一个信息给A,A接收到B返回的信息就会发送一个确认信息给B,然后A与B之间的连接就建立起来了。为什么不是两次握手?因为2次握手的话A不能确认B能接收到自己发送的信息,只有B能确认A能接收自己发送的信息。

    为什么不是四次或者五次或者六次...?三次以后的握手都是多余的,会浪费时间与资源,因为三次握手后双方就能确认对方能够接收到自己发送的信息了。

    详细示例图如下:

    开始的时候,服务器与客户端都是处于Closed状态,然后服务器会有一个端口监听是否有请求过来,这时候状态就处于Listen状态。客户端发送一个SYN尝试与服务器建立连接,然后状态就改变为SYN-Sent。服务器端收到请求后就返回一个SYN,ACK给客户端,然后状态就改变为SYN-Rcvd。客户端再接收到服务器端发送的消息后就返回一个ACK信息,状态跳转为EstabLished。服务器端再接收到客户端发送的ACK消息后就将状态跳转为EstabLished。

    TCP的四次挥手:

    TCP的四次挥手就是为了确认对方没有需要再发送的信息了,然后关闭连接。就比如A说:我没有需要发送信息了。B收到后就回复说:好的我知道了。然后B再发送一个信息说:我也没有需要发送的信息了。A收到后就回复说:好的。这样双方就断开了连接。

    详细的示例图如下:

    再A发送了Fin后就进入了FIN-WAIT-1的状态,B收到A发送的Fin后就会回复一个ACK信息,然后状态就会跳转为Closed-Wait。A在收到了B的ACK信息后就会将状态跳转为Fin-Wait2。如果这个时候B就直接挂断了(跑路),A的状态就不会改变(TCP协议里面没有对这个状态进行处理的机制,但是Linux可以设置tcp_fin_timeout参数,设置超时时间)如果B没有直接挂断,就会发送一个FIN、ACK的信息给A,然后转台跳转为Last-ACK。A在收到B的FIN、ACK信息后就会回复一个ACK信息,并且状态跳转为Time-Wait。如果A在Fin-Wait2的状态时挂断了(跑路)B就不能收到A的ACK信息了。为了防止这种情况的发生,TCP协议要求A最后等待一段时间Time-Wait,这个时间要足够长(如果B没有收到ACK的话,B会重发,A会重新发生一个ACK到B的时间)。

    等待时间设置为2MLS (Maximum Segment Lifetime)报文最大生存时间,它是任何报文在网 络上存在的最长时间,超过这个时间报文将被丢弃。因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 域,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数 据报将被丢弃,同时发送 ICMP 报文通知源主机。协议规定 MSL 为 2 分钟,实际应用中常用的是 30 秒,1 分钟和 2 分钟等。

    如果B 超过了 2MSL 的时间,依然没有收到它发的 FIN 的 ACK,怎么办呢?按照 TCP 的原理,B 当然还会重发 FIN,这个时候 A 再收到这个包之后,A 就表示,我已经在这里等了这么 长时间了,已经仁至义尽了,之后的我就都不认了,于是就直接发送 RST,B 就知道 A 早就跑了。 

    TCP 状态机示例图:

     

    Processed: 0.012, SQL: 9