文章目录
1.TCP传输协议
1.1 简介
TCP是传输层的一种数据传输方式。
以应用层FTP文件传输协议为例,数据的网络传输包(报文)如下:
这里推荐一篇超牛的文章,对TCP的理解非常有意义
一文讲透TCP/IP协议 | 图解+秒懂+史上最全
TCP头部封装形式,更多细节请看大佬讲解,膜拜~~~↑
1.1.1 控制标志位
标志位 | 解释 |
---|---|
ACK | 置1表示确认字段Ack有效;置0表示无效,当SYN为1和ACK为0,Seq字段为(ISN:Initial Sequence Number)初始化序列号是一个随机值(通过算法生成,一般4ms+1) |
FIN | 结束标志位,置1表示发生断开连接请求 |
SET | 复位TCP连接,置1表示连接出现问题,也可以是拒绝接收数据包和拒绝请求 |
PSH | push,置1将数据移交上层,不堆在缓冲区 |
URG | 置1表示紧急指针有效,置0无效 |
SYN | 置1表示紧急指针有效,置0无效 |
1.2 三次握手和四次挥手
只有客户端才能发送连接请求。
三次握手和四次挥手决定了TCP数据传输稳定、准确的特性。
1.2.1 三次握手
诀窍:
Ack是对已接收数据的回应,返回给发送这条数据的发送端,假设A接收B的一条信息,Seq=b,然后A回应的时候Ack值等于a+1 。顾名思义:确认号。
Seq表示自己的数据在整个未分割数据中的顺序,只与自己有关,接着上面假设:B回复A,如果有数据,假设为m字节(没数据为0),在B数据序列号为b,Seq的值为b+m(0),所以B给A的回应为Ack=a+1,Seq=b+(0)。顾名思义:序列号。
1.第一次握手:
客户端发送报文,进入SYN_SENT状态。SYN=1,ACK=0,Seq=a(ISN随机值),添加MSS选项字段,注意区分和MTU的区别。
MSS:数据包有效数据长度。
MTU:数据包的长度。
Linux中数据包的长度为1500字节。可以通过ifconfig查看网络接口和回环接口的信息。
可以看到在网络接口(ens33)信息中,第一行出现了mtu 1500 字样,这就是网络信息传输过程中一个数据包的大小。
关于其他信息的介绍可以看这篇文章:
TCP/IP传输协议,易懂!!!
2.第二次握手:
服务器监听到客户端发来的请求,进入SYN_RECV状态。SYN=1,ACK=1,Seq=b,Ack=a+1,Ack做出响应,为上一次Seq+1,客户端收到Ack=a+1,之后确认服务器能正常发送和接收数据。添加MSS字段。
3.第三次握手:
客户端发送报文,进入ESTABLELISHED状态。SYN=0,ACK=1,Seq=上一字段的Ack,Ack=上一字段Sep+1服务端接收到Ack=b+1,表示客户端成功接受数据,服务端进入ESTABLELISHED状态,连接成功。
1.2.2四次挥手
双方都可以发送断开请求。
四次挥手其实也可以看做是三次,只是多了一层数据保障,防止数据未发送完成导致数据丢失。
1.第一次挥手:
主动断开方发送FIN=1,ACK=0,Seq=a(ISN)报文,进入FIN_WAIT1状态。
2.第二次挥手:
被动方接受到断开请求之后,被动断开方发送FIN=0,ACK=1,Seq=b,Ack=a+1报文,表示收到断开连接请求,但是我可能还有数据没发送完成请等等我,被动方进入CLOSE_WAIT状态。之后被动方告知应用层,准备断开连接,是否有数据发送,如果有主动方还能接收数据。主动方接收到报文后进入FIN_WAIT2状态。
3.第三次挥手:
3.1有数据:(假设一次就能发送完)
确定用户数据发送已完成,给主动方发送FIN=1,ACK=1,Seq=c, Ack=b+1 (c是未发送数据在整个数据中的 序列号,这个值我认为是有保存的,不然发送过去的数据无序,或者Seq=a+2,有可能在接收端直接在尾部添加)。
3.2:没数据
确定没数据,直接默认模式Ack(n) = Seq(n-1)+1, Seq(n)=Ack(n-1)。FIN=1,ACK=1,Seq=a+2,Ack=b+1。
4.第四次挥手:
主动方发送FIN=0,ACK=1,Seq=b+1,Ack=a+3。被动房接收到报文后退出,而主动断开方在TIME_WAIT状态等待2*MSL。
1.2.3 MSL:
MSL(Maximum Segment Lifetime)即报文最大生存时间,它是一个经验值。
在不同的操作系统中,MSL 的值可能会有所不同,通常在 30 秒到 2 分钟之间。
所以 2*MSL 的时间就是两倍的报文最大生存时间,大约在 1 分钟到 4 分钟之间。
设置主动断开方在 TIME_WAIT 状态等待 2*MSL 时间主要是为了确保在网络中延迟的报文都已经消失,防止新建立的连接受到旧连接中延迟报文的影响,从而保证连接的可靠关闭和网络通信的稳定性。
1.3 问题
1.3.1为什么建立三次连接,两次一个来回不行吗?
一个来回,客户端只进行了发送数据,而服务器进行了接收和发送,不能保证客户端接收是否正常,所以要进行三次连接是为了验证客户端和服务端发送和接收都是正常的。
1.3.2 为什么FIN和SYN只有两次置1?
FIN和SYN的目的是断开和连接的请求和响应,请求和发送两次就够了。比如SYN,服务器收到数据包看到SYN=1,必然是连接请求,客户端接收到SYN=1,必然是服务器的请求响应。假如说多了一次,那还得判断这是第几次接收的FIN,该如何处理,有点画蛇添足了。