zoukankan      html  css  js  c++  java
  • TCP三次握手&四次挥手

    TCP概述

    网络分为IOS七层协议:物理层、数据链路层、网络层、传输层、会话层、表现层、应用层

    TCP协议属于传输层的协议

    TCP数据包结构图

    在进行握手时,就依赖着结构中的序号确认号

    TCP中的标识符

    SYN:同步标志

    同步序列编号(Synchronize Sequence Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号

    ACK:确认标志

    确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure-1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据

    URG:紧急标志

    紧急(The urgent pointer) 标志有效,紧急标志置位

    FIN:结束标志

    带有该标志置位的数据包用来结束一个TCP会话,但对应端口仍处于开放状态,准备接收后续数据
    三次握手Three-way Handshake

    三次握手

    一个虚拟连接的建立是通过三次握手实现的

    示意图

    三次握手流程

    1. B的TCP服务器进程先创建传输模块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求
    2. 第一次握手:A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,此时首部中的同部位SYN = 1,同时选择一个初始序号seq = x(这个指令的意思就是告诉B客户机自己的序号是多少,要接着这个序号发送数据报)。TCP规定,SYN报文段(即SYN = 1的报文段)不能携带数据,但是要消耗一个需要。此时TCP客户进程进入SYN-SENT(同步已发送)状态
    3. 第二次握手:B收到连续请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置为1,确认号是ack = x + 1,同时自己也为自己选择一个初始序号 seq = y。(注意:这个报文段也不能携带数据,但同样需要消耗掉一个序号)。这时TCP服务器进程进入SYN-REVD(同步收到)状态
    4. 第三次握手:TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号ack = y + 1,而自己的序号seq = x + 1。TCP的标准规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是 seq = x + 1。这时,TCP连接建立,A进入ESTABLISHED(已建立连接)状态,当B收到A的确认消息后,也进入ESTABLISHED状态

    注:最后一次握手在默认不携带数据的情况下,由于SYN不是1,是不消耗序列号的。所以三次握手结束后,客户端下一个发送的报文中seq依旧是x + 1

    为什么需要三次握手,而非两次?

    • 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
    • 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认

    四次挥手

    一个虚拟连接的断开是通过四次挥手实现的

    示意图:

    四次挥手流程:

    1. 第一次挥手:A数据传输关闭,需要断开连接,A应用进程向其TCP发出连接释放报文段(FIN = 1, seq = u),并停止在发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认
    2. 第二次挥手:B收到连接释放报文后即发出确认报文段(ACK = 1,确认号ack = u + 1,序列号seq = v),B进入CLOSE-WAIT关闭等待状态,此时的TCP处于半关闭状态,A到B的连接释放。而A收到B的确认后,进入FIN-WAIT-2状态,等待B发出的连接释放报文段
    3. 第三次挥手:当B数据传输完毕,B发出连接释放报文段(FIN = 1ACK = 1,序号seq = u + 1,确认号 ack = u + 1),B进入LAST-ACK(最后确认)状态,等待A的最后确认
    4. 第四次挥手:A收到B的连接释放报文段后,对此发出确认报文段(ACK = 1seq = u + 1ack = w + 1),A进入TIME-WAIT(时间等待)状态,此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSE状态

    为什么A在TIME-WAIT状态必须等待2MSL(最大报文生存时间)的时间?

    为了保证A发送的最后一个ACK报文段能够到达B,保证A、B正常进入CLOSED状态

    这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,A能2MSL时间内收到这个重传的FIN+ACK报文段,接着A重传一次确认,同时重启2MSL计数器,2MSL时间后A和B进入CLOSE状态,如果A在TIME-WAIT状态时接收到B的FIN+ACK报文段之后向B发出确认报文段,而不再确认B是否收到立即进入CLOSED状态,如若B并没有正常收到A 的确认报文段,则B无法正正常进入到CLOSED状态

    人生没有白走的路,每一步都算数
  • 相关阅读:
    c#实现windows远程桌面连接程序
    基于.NET平台常用的框架整理
    c#无限循环线程如何正确退出
    c# 内存的具体表现- 通用类型系统 深拷贝 浅拷贝 函数传参
    coco2d-x convertToWorldSpace介绍
    Effective C++条款20:宁以pass-by-reference-to-const替换pass-by-value。Test code
    函数指针与指针函数返回值的区别
    游戏开发那些事
    lua 根据指定字符拆分table字符串(转载)
    实习和学习的双重压力
  • 原文地址:https://www.cnblogs.com/erhuoweirdo/p/14531676.html
Copyright © 2011-2022 走看看