TCP三次握手与四次挥手

这里主要记录在平常中对知识的学习,经过结合笔记与自身理解的方式尝试写下总结
文章对细节可能不会一一介绍解释,内容仅做参考
复制代码

前段时间看了HTTP相关的知识,但感受还有还多细节面没有了解到位。此次补充与TCP链接有关的服务器

1、头部字段

一些须要前置了解的知识点网络

  • Sequence number 顺序号码:保证TCP传输的报文都是有序的
  • Acknowledge number 确认号码:表示数据接收端指望接收的下一个字节的编号是多少,并表示上一个序号已接收完成
  • 确认方Ack = 发起方Req+1,两端配对
  • Window Size 窗口大小:表示还能接收多少字节的数据,用于流量控制
  • RTT:表示发送端发送数据到接收到对端数据所需的往返时间

标识符:学习

  • URG=1: 表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据必定位于当前数据报数据部分的最前面,紧急指针标明了紧急数据的尾部
  • ACK=1: 表示确认字段有效。TCP还规定在链接创建后传送的全部报文段都必须把ACK置为1
  • PSH=1: 表示接收端应该当即将数据push给应用层,而不是等到缓冲区满后再提交
  • RST=1: 表示当前TCP链接出现严重问题,可能须要从新创建TCP链接,也可能用于拒绝非法的报文段和拒绝链接请求
  • SYN=1: 当SYN=1,ACK=0时,表示当前报文段是一个链接请求报文;当SYN=1,ACK=1时,表示当前报文段是一个赞成创建链接的应答报文
  • FIN=1: 表示此报文段是一个释放链接的请求报文

2、三次握手

在TCP协议中,主动发起请求的一端为客户端,被动链接的一端为服务端。不论是客户端仍是服务端,TCP链接创建完成后都能发送和接收数据,因此TCP是一个全双工的协议spa

一次TCP的创建须要进行三次对话,从而肯定一个链接,进而开始通信3d

过程如图所示:指针

  • 第一次握手:客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通信初始序号Seq=X和链接请求SYN。请求发送后,客户端进入SYN-SENT状态
  • 第二次握手:服务端收到连接请求报文段后,若是赞成链接,则会发送一个包含自身的数据通信初始序号Seq=Y、确认序号Ack=X+1和应答标识ACK的确认应答。发送完成后,服务端进入SYN-RECEIVED状态
  • 第三次握手:当客户端收到链接赞成的应答后,还要向服务端发送一个确认报文(Ack=Y+1,Seq=Z,ACK)。客户端发完这个报文段后进入ESTABLISHED状态,此时链接创建成功

明明两次握手就能够创建链接,为何还须要第三次应答呢:code

由于这是为了防止失效的链接请求报文段被服务端接收,从而产生错误cdn

若是是这样:客户端发送了一个链接请求A,可是由于网络缘由形成了超时,这时TCP会启动超时重传的机制再发送一个链接请求B。此时请求B顺利到达服务端,服务端应答完成就创建链接。若是链接请求A在两端关闭后终于到达了服务端,那么这时服务端会认为客户端又须要创建TCP链接从而应答后进入ESTABLISHED状态。此时客户端实际上是CLOSED状态,那么就会致使服务端一直等待,形成资源浪费blog

在创建链接中,任意一端掉线,TCP都会重发SYN包,通常会重试5次,在创建链接中可能会遇到SYN FLOOD攻击,能够选择调低重试次数或干脆在不能处理的状况下拒绝请求资源

3、四次挥手

TCP是全双工的,在断开链接时两端都须要发送FIN断开请求和ACK确认

过程如图所示:

  • 第一次挥手:客户端认为数据发送完成,向服务端发送链接释放请求
  • 第二次挥手:服务端收到链接释放请求,会告诉应用层要释放TCP链接。而后发送确认应答,并进入CLOSE_WAIT状态,表示客户端到服务端的链接已经释放,不接收客户端发的数据了。可是由于TCP链接是双向的,因此服务端仍旧能够发送数据给客户端
  • 第三次挥手:若是此时服务端还有没有发完的数据,会继续发送。等到发送完毕后会向客户端发送链接释放请求,并进入LAST-ACK状态
  • 第四次挥手:客户端收到释放请求后,会向服务端发送确认应答。此时客户端进入TIME-WAIT状态,会持续2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃),若该时间段内没有服务器的重发请求的话,就进入CLOSED状态。当服务端收到确认应答的时候,也进入了CLOSED状态

为何客户端要进入TIME-WAIT状态,等待2MSL后才进入CLOSED状态呢:

为了保证服务端能收到客户端的确认应答。若客户端发完确认应答后直接进入CLOSED状态,若是确认应答由于网络问题一直没有到达,那么会形成服务端不能正常关闭

为何链接的时候是三次握手,关闭的时候倒是四次握手:

由于当服务端收到客户端的SYN链接请求报文后,能够直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。可是关闭链接时,当服务端收到FIN报文时,极可能并不会当即关闭SOCKET,因此只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我服务端全部的报文都发送完了,我才能发送FIN报文,所以不能一块儿发送。故须要四步握手