• 三次握手与四次挥手


    什么是三次握手

    三次握手(Three-way Handshake)是指在建立一个TCP连接时,需要客户端和服务器总共发送三个包。进行三次握手的主要作用是为了确认双方的接受能力和发送能力是否正常、指定自己的初始化序列号为后面可靠性传输做准备。

    实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小的信息。滑动窗口本质上是描述接受方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据。如果发送方收到接受方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接受方发送窗口大小不为0的数据报的到来。

    过程描述:

    刚开始客户端处于closed状态,服务端处于listen状态。

    第一次握手,客户端给服务端发送一个SYN报文,并指明客户端的初始化序列号ISN(c)此时客户端处于SYN_SEND状态。首部的同步位SYN=1,初始序号为seq=xSYN=1的报文段不能携带数据,但是需要消耗掉一个序号。

    第二次握手,服务器接受到客户端的SYN报文之后,会以自己的SYN报文进行应答,并且指定了自己的初始化序列号ISN(s)同时会把客户端的ISN+1作为ACK的值,表示自己已经收到了客户端的SYN,此时服务器处于SYN_REVD状态。在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。

    第三次握手,客户端收到SYN报文之后,会发送一个ACK报文,一样也会把服务器的ISN+1作为ACK的值,表示已经收到了服务端的SYN报文,此时客户端处于ESTABLISHED状态。服务器收到ACK报文后也处于ESTABLISHED状态,此时双方建立起连接。在确认报文段中ACK=1,确认号ack=y+1,序号seq=x+1(初始seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。

    发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)。

     

    ISN是固定的吗?

    不是,ISN随着时间而变化,因此每个连接都会具有不同的ISN,这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致连接的一方对它做错误的解释。

    三次握手的意义:

    第一次握手:客户端发送网络包,服务端收到。服务端可以确定:客户端的发送能力,服务端的接收能力正常。不可以携带数据

    第二次握手:服务端发包,客户端收到。客户端可以确定:服务端的发送与接收能力正常,客户端的发送接收能力正常。但是服务端无法确定客户端的接收能力是否正常。不可以携带数据

    第三次握手:客户端发包,服务端接收到,这样就确定了双方的发送接收能力都正常。可以携带数据

    什么是四次挥手

    建立一个连接需要进行三次握手,而终止一个连接需要经过四次挥手。这是由TCP的半关闭(half-close)造成的。半关闭TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。

    TCP的连接的拆除需要发送四个包,因此被称为四次挥手(Four-way handshake),客户端服务器均可以发起挥手的动作。

    过程描述:

    刚开始双方都处于ESTABLISHED状态,假如是客户端线发起关闭请求,过程如下:

    第一次挥手:客户端发送一个FIN报文,报文中指定一个序列号。此时客户端处于FIN_WAIT1状态,发出连接释放报文段,FIN=1,序号seq=u,并且停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。

    第二次挥手:服务端收到FIN后,会发送ACK报文,且把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到客户端的报文了,此时服务端处于CLOSE_WAIT状态。服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FINWAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。

    第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发送一个FIN报文,且指定一个序列号。此时服务端处于LAST_ACK的状态,服务端没有向客户端发出的数据,服务器发出的连接释放的报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认状态),等待客户端确认。

    第四次挥手:客户端收到FIN后,一样发送一个ACK报文作为应答,且把服务端的序列号值+1作为自己的ACK报文序列号值,此时客户端处于TIME_WAIT状态。需要过一阵子确保服务端收到自己的ACK报文才进行关闭进入CLOSED状态,服务端收到ACK报文后,关闭连接进入CLOSED状态。客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态,此时TCP未释放掉,需要经过时间等待计时器设置的事件后,客户端才进入CLOSED状态。

    挥手为什么需要四次:

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

  • 相关阅读:
    使用echarts插件做图表常见的几个问题(五)——图形的两种渲染方式
    数组对象如何根据对象中某个字段分组
    JS监听浏览器后退事件
    使用echarts插件做图表常见的几个问题(四)—— 柱状图中以虚线展示重合的柱子
    使用echarts插件做图表常见的几个问题(三)—— 图表标线的使用
    使用echarts插件做图表常见的几个问题(二)—— 实现多Y轴
    使用echarts插件做图表常见的几个问题(一)—— 折线图局部虚线
    如何判断touch事件滑动的方向?
    解决session共享方案
    设计模式总结
  • 原文地址:https://www.cnblogs.com/plutozzl/p/11723257.html
Copyright © 2020-2023  润新知