概述

  • 传输Http前的操作
    http协议只定义了应用层的东西,下层的可靠性要传输层来保证,如TCP,可以看出http协议是基于TCP协议的。
    需要先建立TCP连接,后HTTP传输
    图片说明

TCP连接是可靠的,需要建立连接,让两方互相感受到对方的存在,通过下面两个策略来连接/断开两方之间的连接

三次握手

1. ACK 跟 ack

  1. 一个是确认值(Acknowledgement),为1便是确认连接。
  2. 另一个是确认编号(Acknowledgement Number),即接收到的上一次远端主机传来的seq然后+1,再发送给远端主机。提示远端主机已经成功接收上一次所有数据。

2. 三次握手图解

  • 图解
    图片说明

对于网络中滞留的请求包,例如客户端第一次发出握手后,恰逢网络堵塞,因为超时重传机制,客户端又发送一系列握手请求成功建立连接。现在网络堵塞的那个包生效了,到达了服务器。服务器直接向客户机发送确认指令即可,无需消耗过多的资源,回到客户端后客户端会发现这条数据不是客户端的有效数据包,则不理睬

服务器于是继续等待应答包。这样服务器端的连接一直保持在SYN_RCVD状态(半开连接)直到超时

3. 补充知识

服务器发送SYN-ACK包:
  1. 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
  2. 注意,每次重传等待的时间不一定相同
文字的三次握手
  1. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

  2. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

  3. 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,建立成功就完成三次握手。

  4. 完成三次握手,客户端与服务器开始传送数据

建立过程中传送的包
  1. 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。
  2. 传输消耗一个序号seq
  3. 理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
半连接存活时间
  1. 是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。
  2. 我们也称半连接存活时间为SYN_RECV存活时间。
为什么TCP客户端最后还要发送一次确认呢?
  1. 主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

  2. 如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

  3. 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

4. 为什么不能用二次握手

  • 原因一:
    图片说明

  • 原因二:
    图片说明

5. 为什么不能用四次握手

  • 原因:
    图片说明

四次挥手

1. 挥手图解

  • 图解
    图片说明
    第二次挥手是发送确认信号
    第三次挥手是发送请求信号 【区分于三次握手 这里作用是提供给剩余数据一个发送时间】

2. 挥手文字补充

服务器收到ACK前的一刹那,客户端可能因为没收到ACK而重传了一个FIN报文,这个FIN报文要从网络中消失最多还需要一个MSL时长,所以客户端还需要多等一个MSL。

  1. 如果客户端发送FIN,没有收到服务器的FIN-ACK回应,会多次发FIN请求给服务器,持续几分钟

  2. 服务器被动关闭处在LAST_ACK,在接收客户端最后一个ACK回应后,不发送任何报文,进入close状态

  3. 客户端在接收到服务器的FIN报文时,会回复一个ACK报文并进入TIME-wait状态

  4. TIME_WAIT状态需要维持一段时间而不是进入CLOSED状态,是来解决服务器可能重传的FIN报文或其它一些因网络原因而延迟的数据报文。不处理这些会对下次连接或者本次数据造成影响

  5. 处于TIME_WAIT状态的一端在收到重传的FIN时会重新计时

3. 挥手的知识补充

2MSL
  • 2个MSL中的第一个MSL是为了等自己发出去的最后一个ACK从网络中消失,
  • 第二个MSL是为了等在对端收到ACK之前的一刹那可能重传的FIN报文从网络中消失。
  • 某些滞留的数据可能会混淆下次连接,需要将其彻底解决掉。【服务器重发的FIN,可能会影响下一次连接,需要将其铲除】
  • 如果2MSL没有再接收到数据则可以放心断开
  • ACK报文在网络中丢失;如前所述,这种情况我们不需要考虑,因为除非多次重传失败,否则AB两端的状态不会发生变化直至某一个ACK不再丢失。 也就是会客户端发送的ACK不用几次就会到达服务器

资料