TCP的三次握手和四次挥手

TCP中两个序号和三个标志位的含义

  • seq: sequence number缩写,表示传输数据的序号,发送数据时会将数据的序号发给对方,接收方按序号检查数据是否完整
  • ack: acknowledge number缩写,表示确认号,值为期望接收的下一个数据报的起始序号(seq + 1)
  • ACK: 确认位,只有ACK = 1 时ack才起作用,正常通信时ACK = 1,而当建立通信时因为没有需要确认的数据此时ACK = 0
  • SYN: 同步位,用于在建立连接时同步序号。刚建立连接时没有接收的历史数据,ack也没法设置,当接收端收到SYN = 1时,会将ack不经过校验直接设置为seq + 1,这就作为了ack的初始值,SYN在前两次握手时都为1,这样通信双方都会有ack的初始值
  • FIN: 终止位,在数据传输完毕后释放连接

传输过程图

问题

  • 为什么需要三次握手而不是两次握手

    TCP传输模式是全双工模式,Server端和Client端是完全对等的,三次握手前两次可以确保Server端可以正常接收并返回请求,后两次可以确保Client端可以正常接收并返回请求

  • 为什么握手要三次,挥手却要四次

    因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手

  • SYN Flood攻击

    Client端在发送第一次握手信息(并接收到第二次握手)之后不回应第三次握手,服务器会以为第二次握手包在传输过程中丢失,会持续发送第二次握手(通常会持续发送5次),如果有大量这种恶意请求,服务器就会大量浪费服务器资源

    解决方法:

    • 适当调小第二次握手包的重发次数
    • 当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:$ netstat -nap | grep SYN_RECV
01-25 04:53