TCP的6种标识
- SYN(建立联机)
- ACK(确认)
- PSH(传送)
- FIN(结束)
- RST(重置)
- URG(紧急)
TCP 三次握手
第一次:
客户端想要和服务端建立连接
SYN = 1,生成随机初始化序列号 seq = x
客户端 => SYN-SENT (同步已发送状态)
TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但也需要消耗一个序号
第二次:
询问客户端是否准备好
服务器发送确认报文。ACK = 1,SYN = 1,确认号 ack = x+1,生成随机初始化序列号 seq = y
服务端 => SYN-RCVD(同步收到状态)
这个报文也不能携带数据,带有SYN(建立连接)和 ACK(确认)标志
第三次:
客户端表示我已准备好
客户端收到确认后,向服务器给出确认
ACK= 1,ack = y+1
客户端 => ESTABLISHED(已建立连接状态)
TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号
为什么不进行两次握手?
场景: 已失效的连接请求报文段
客户端 => 服务端 网络问题,数据超时到达
服务端 服务端收到,开始建立连接
状态:失效的报文
问题:服务端认为新的连接已经建立起来了,并且等待客户端发来数据,导致server资源浪费
总结:如果server收不到确认的报文,就知道client并没有建立连接。
TCP四次挥手
第一次:
客户端发出连接释放报文,并且停止发送数据
FIN = 1,序列号 seq=u(等于前端已经传送过来的数据的最后一个字节的序号加1)
客户端 => FIN-WAIT-1(终止等待1)。消耗序列号
FIN报文段即使不携带数据,也需要消耗一个序号
第二次:
服务端收到这个FIN并发回一个ACK(确认)
ACK=1,ack=u+1,seq = v
服务端 => CLOSE-WAIT(关闭等待状态)
半关闭状态,客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受
客户端收到服务器的确认请求后,客户端进入FIN-WAIT-2(终止等待2)等待服务器发送连接释放报文
第三次:
服务端发送一个FIN(结束)到客户端,服务端关闭客户端的连接
FIN = 1, ack = u+1,由于在半关闭状态,服务器可能又发送一些数据
服务端 => LAST-ACK(最后确认状态)等待客户端的确认
第四次:
客户端发送ACK(确认)报文,并将确认的序号+1,这样关闭完成
ACK = 1,ack=w+1,seq = u+1
客户端 = > TIME-WAIT (时间等待)状态
注意:此时的TCP连接还没有释放,必须经过 最长报文段寿命 的时间后。当客户端撤销相应的TCP后,才进 入CLOSED状态。
服务器 收到客户端发出的确认 立即进入 CLOSED状态
=> 服务器结束TCP连接的时间要比客户端早一些
为什么需要进行四次挥手?
客户端 => 服务端 server端收到FIN报文时,存在可能不会立即关闭socket.
只能先回复一个ACK报文,告诉client。“你发的FIN报文我收到了”
服务端 => 客户端
服务端 => 客户端 server端所有的报文都发送完了。这时候才会发送FIN
客户端 => 服务端 客户端发送ACK(确认)报文确认。关闭连接
总结: 为了确保数据能够完成传输。因为未必会马上关闭socket,可能还需要发送一些数据给对方。