计算机网络(一)TCP三次握手以及四次挥手

1. 计算机网络分层

OSI模型

  • 物理层
  • 数据链路层
  • 网络层
  • 传输层
  • 会话层
  • 表示层

物理层:定义了物理设备的标准,传输比特流(二进制数据转换为强弱不同的电流,到达目的后再转换为机器码)

数据链路层:定义了如何格式化数据以及如何传输,提供错误检测以及纠正,将比特数据转换为帧

网络层:将网络地址翻译为对应的物理地址,并决定将数据从发送方路由到接收方,选择最佳路由。IP协议,IP数据包

传输层:接受上一层的数据,在必要的时候将数据进行分割。并将这些数据交给网络层,且保证这些数据段有效的到达接收方。TCP协议,UDP协议

会话层:自动收发包,自动寻址。在不同机器上的用户之间建立及管理会话,接触或建立与别的节点的联系

表示层:解决不同系统之间通信语法不同的问题,数据加密,代码转化、将数据以网络能理解的方案进行格式化。

应用层:规定接收方和发送方以一个固定长度的消息头,例如文件传输、电子邮件、文件服务、虚拟终端等。HTTP协议

2. TCP/IP协议

TCP:传输控制协议

  • 面向连接的、可靠的、基于字节流的传输层通信协议
  • 将应用层的数据流分割成报文段并发送给目标节点的TCP层
  • 数据包都有序号,保证到目标节点的按序处理。对方收到则发送ACK确认,如果在合理的往返时延内未收到确认则重传
  • 使用检验和来检验数据在传输过程中是否有误

TCP报文头部结构
在这里插入图片描述

  1. 源端口和目的端口: 各占2个字节,分别写入源端口号和目的端口号,源端口号在需要对方回信时选用,目的端口在终点交付报文的时必须使用

  2. 序号:在一个TCP连接中传送的字节流中的每一个字节都按顺序编号

  3. 确认号:是期望收到对方下一个报文段的第一个数据字节的序号。若确认号 = N,则表明:到序号N-1为止的所有数据都已正确收到

  4. 数据偏移: 指出TCP报文段的数据起始处距离TCP报文段的起始处有多远

  5. Flags

    • URG:紧急指针标志,为1表明紧急指针有效,告诉系统此报文段中有紧急数据,优先级高
    • ACK:确认序号标志,仅当ACK=1时确认号字段才有效。TCP规定,在连接建立后所有穿梭那个的报文段必须把ACK置为1
    • PSH:push标志,用于提高优先级
    • RST:重置连接标志,当RST=1时,表明TCP连接中出现严重差错,必须释放连接并重新建立连接
    • SYN:在连接时用来同步序号,当SYN=1而ACK=0时,表明这是一个连接请求的报文段,对方若同意建立连接,则响应的报文端中ACK=1且SYN=1。
    • FIN: 用于释放一个连接,当FIN=1时,表明此报文段数据已发送完毕,并要求释放连接。
  6. 窗口: 窗口值作为接收方让发送方设置其发送窗口的依据,用于流量控制

  7. 检验和: 检验和字段检验的范围包括首部和数据两部分

  8. 紧急指针: 仅在URG=1时才有效,用于指出本报文段中的紧急数据的字节数。

  9. 可选项: 仅用于使整个TCP报文的首部长度是4的整数倍

TCP的三次握手
在这里插入图片描述

  1. 假设A、B首次建立通信
  2. 服务端创建传输控制块TCP时刻监听客户端发送的请求,服务端进入Listen状态
  3. 客户端创建传输控制块TCP向服务器发送连接请求报文,SYN=1 初始序号为 x,客户端进入SYN-SENT(同步已发送)状态 (第一次握手)
  4. 服务端收到请求报文后,若同意建立连接,则向A发送确认报文段、在确认报文段中应把ACK 和 SYN都置为1,确认号ack=x+1(因为请求报文段中消耗了一个序号)、为自己的缓存初始化序列号seq=y。服务端进入SYN-RCVD(同步收到)状态 (第二次握手)
  5. 客户端接收到服务端的确认报文后,还要给服务端发送确认报文,确认报文中ACK=1、确认号ack=y+1,自己的序号seq=x+1,这时TCP连接已经建立,客户端和服务端进入ESTANLISHED(已建立连接)状态 (第三次握手)

为什么需要三次握手才能建立连接

  1. 为了初始化seq(序号)的初始值,以保证传输的数据不会因为网络上的问题而乱序

  2. 首次握手时的隐患——SYN超时

    • 问题起因分析

      1. 客户端收到服务端的SYN,回复的SYN-ACK的时候未收到ACK确认

      2. 服务端不断重试直至超时,Linux默认等待63s才能断开连接

        • 针对SYN Flood的防护措施

          • SYN队列满后,通过tcp_syncookies参数回发SYN Cookie
          • 若为正常连接则服务端会回发SYN-COOKIE,直至完成连接
      3. 建立连接后,客户端出现故障怎么办

        • 向对方发送保活探测报文,如果未收到响应则继续发送
        • 尝试次数打到保活探测数仍未收到响应则中断连接

TCP的四次挥手
在这里插入图片描述

  1. 假设数据传输过程中,由客户端进程主动关闭,则服务端被动关闭

  2. 客户端进程先向其TCP发送***连接释放***报文段,并停止再发送数据,连接释放报文段中将终止控制位FIN置为1,seq=u(等于已传送过的数据的最后一个字节的序号加1)客户端进入FIN–WAIT-1(
    终止等待)状态,等待B确认。FIN报文段即使不携带数据,它也消耗一个序号。 (第一次挥手)

  3. 服务端进程收到连接释放报文段后即发出确认,确认号是ack=u+1,seq为v(等于客户端前面已传送的数据的最后一个字节的序号加1),然后服务端进入CLOSE-WAIT(关闭等待)状态。TCP服务器此时会通知高层应用进程,因为从客户端到服务端这个方向的连接就被释放了,这是TCP连接处于半关闭状态,这时客户端已经没有数据向服务端发送了,但是服务端要发送数据,客户端仍要接收。也就是说,从服务端到客户端这个方向的连接还没有关闭,这个状态可能会持续一段时间。(第二次挥手)

  4. 客户端收到服务端的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待服务端发送的连接释放报文段。

  5. 若服务端已经没有向客户端发送的数据,其应用程序就通知TCP释放连接,这时服务端发送的连接释放报文必须时FIN置为1,假定服务端进程的序号为w(在半关闭状态可能又发送了一部分数据)。服务端还必须重复上次已经发送的确认号ack=u+1,这时服务端进程进入LAST-ACK(最后确认)状态,等待客户端的确认。 (第三次挥手)

  6. 客户端收到服务端发送的连接释放报文后,必须对此进行确认。在确人报文段中吧ACK置为1,确认号ack=w+1,而自己的序号seq=u+1,然后进入TIME-WAIT(时间等待)状态。此时客户端进程的TCP连接还没有释放掉,必须等待时间等待计时器设置的时间2MSL之后,客户端才能进入CLOSED状态。RFC793建议为2min,Linux为30s,而服务端接收到客户端的确认报文后,立即进入CLOSED状态关闭连接。(第四次挥手)

为什么会有TIME-WAIT状态(为什么要等待2MSL)

  1. 确保有足够的时间让对方收到ACK包
  2. 避免新旧连接混淆

为什么需要四次挥手才能断开连接

  1. 因为TCP协议是全双工,发送方和接收方都需要FIN报文和ACK报文

服务器出现大量CLOSE_WAIT状态的原因

  1. 客户端发送了一个连接释放的报文之后,服务器端没有发送确认报文,即客户端关闭了socket连接,但服务端忙于读或写,没有及时的关闭连接。

    • 检查代码,特别是释放资源的代码
    • 检查配置,特别是处理请求的线程配置
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章