三次握手四次挥手

1.背景

在说三次握手和四次挥手之前我们先得提一下,我们知道tcp相对于udp,它是一种可靠,面向连接可靠的字节流服务。在传输层使用tcp协议是面向连接,就意味着要把服务器和客户端交换数据之前需要建立连接。这里连接就是所谓的(三次握手),断开连接就是所谓的(四次挥手)。

2.TCP报文


三次握手四次挥手

16位端口号:告诉主机报文来自哪个端口,要传给哪个端口

32位序号:当我们使用TCP协议给对方发送一串字节流时候,这时候我们发现,字节流可能会被分成好几个tcp报文发送过去。这几个报文可能不一定按顺序到达。那么这个时候序号就体现出它的作用了。我们建立新连接时候,第一字节序号就是初始序号ISN,也就是三次握手成功的第一个报文段。我们在一次连接中,在一个方向上。(我们知道socket是全双工的)该报文序号就是对应着字节流的上的偏移(可以近似看成一个累加的过程)。假设现在发一个helloworld字节流, 被分成两个tcp报文段发送了。分别是hell    oworld,假设hell这个报文段的序号是35354911,那么它发的第二个oworld报文的序号就应该是35354915。

32位确认号:这个很好理解,我们知道TCP是可靠的字节流服务。可靠不是说传输数据过程数据不会丢包。而是丢包了会重传。那么问题来了。我怎么知道你是否丢包了呢?这里就引出了确认号。在主机A和主机B进行通信时候,我们不仅仅发送自己的序号。同时也会发送TCP报文段的确认号。其值就是收到的TCP报文段序号+1。

6位标志位包含如下:

ACK标志:表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。

SYN标志:表示请求一个连接,我们称携带SYN标志的TCP报文为同步报文段。同步报文段即使没有携带应用程序数据,它也要占用一个序号。

FIN标志:表示通知对方本端要关闭连接了。


3.三次握手

三次握手四次挥手

(seq就是序号,ack就是确认号)第三次握手时候seq=x+1就是前面所说的,同步报文段即使程序没有发送字节流,字节序还是会+1。

三次握手的过程:

1)主动开启者(这里我们先认为是客户端)发送一个SYN报文段(就是TCP头部的SYN位字段置位TCP/IP数据包)。这里就指明自己的ISN。也就是初始字节序。本次连接的客户端的ISN是x。

2)服务器收到客服端发过来的SYN报文,会发出自己的SYN报文段作为响应,并包含了它的初始***。此外这个报文段也会去确认客服端的SYN,回复一个ACK。确认号的值是收到的报文段的序号值+1 。这次连接服务器的ISN是y确认号是x+1。

3)为了确认服务器的SYN,客服端ISN的数值+1作为ACK,回复给服务器。

这样三次握手就完成了。这次握手也承载了特殊的信息,那就是交换了初始***。

4.为什么三次握手不能变成二次

首先我们要明白一点变成二次握手是怎么样子我简单画个图

三次握手四次挥手

这是我理解假设变成两次握手了。会哪些不好的地方呢,第一点这个连接太不可靠了。这样的话服务器太被动了(你发个SYN就和你建立连接了)。假设客服端A发送了一个SYN,由于网络延迟滞留了。但是却是一个失效的同步报文段。最后服务器B接收到了,就和客服端A建立了连接。不需要客服端A确认。这样就建立了连接,还去等待客服端A发送数据。这样会服务器的资源的。这种也大都是书上描述。

细细想想其实就算是三次握手也能被攻击造成浪费资源,假设客服端利用SYN攻击一直就第一次握手不回复ACK。那么服务器其实也要维护一个半开连接的队列,这个队列是不是资源呢?这个队列如果挤爆了。是不是同样也会让想要连接的客服端被丢失呢?解决方法

方案1:就是给这个半开队列设置上限值,当超过这个上限值就会开始舍弃掉队列中的一部分信息。这样就能给队列腾出新的空间。这个方案肯定有弊病的就是如果把需要真正连接的信息数据舍弃掉了呢?

方案2:就是把这个先不分配tcp,先存放到HASH表中,等客户端回复了ACK之后再分配TCB。


5.四次挥手

三次握手四次挥手

1)主动方(这里理解为客户端)发送FIN(把FIN标志位置位的报文段)给被动方(这里理解为服务器)。客户端发完FIN变为FIN_WAIT_1状态。表示自己没有要发的数据了

2)服务器收到FIN立马回复ACK之后进入COLSE_WAIT状态,这个时候客户端收到ACK,变成FIN_WAIT_2.

3)服务器这时候把没发送的数据这时候发完,然后发送FIN进入LAST_ACK

4)当客户端发送了ACK之后就进入TIME_WAIT状态了。当服务器收到ACK就close

6.为什么要有TIME_WAIT状态

作用1就是如果此刻客户端发送ACK丢失,要求重发一份FIN的请求,客服端是不是该回复一个ACK,重新进入TIME_WAIT。不然直接closed的话呢就没有办法超时重传了.

作用2如果没有TIME_WIAT状态,立即关闭的话呢,这时候立即建立好一个(相同ip和端口的客户端)的连接。在网络中没有被丢弃的数据是不是会传送到这个客户端上呢。


7.TCP状态转移图

三次握手四次挥手

这个图里注意下RST,和同时建立连接和同时关闭连接的情况

RST是三次握手失败的情况下,发送RST报文和收RST报文

第一种是服务器收到SYN,回复ACK和SYN超时得不到回应就发RST报文然后close。

第二种是服务器收到RST报文就进入LISTEN状态

同时建立连接发生,相当于两者都进入了SYN_SENT状态然后再发ack进入正常连接状态

同时断开连接,两者同时发送FIN,进入FIN_WAIT_1然后收到FIN,发ACK进入COLSING状态,收到ACK就两个都得进入TIME_WAIT状态,然后closed。