• TCP协议分析(一)


          传输控制协议(Transmission Control Protocol, TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

    1、OSI七层模型简介

      TCP协议和UDP协议共同工作在OSI七层模型中的第四层-传输层,OSI七层模型如下:

    OSI 模型
     数据单元功能
    主机层 Data数据 7. 应用层 网络进程到应用程序。
    6. 表示层 数据表示形式,加密和解密,把机器相关的数据转换成独立于机器的数据。
    5. 会话层 主机间通讯,管理应用程序之间的会话。
    Segments数据段 4. 传输层 在网络的各个节点之间可靠地分发数据包。
    媒介层 Packet/Datagram数据包/报文 3. 网络层 在网络的各个节点之间进行地址分配、路由和(不一定可靠地)分发报文。
    Bit/Frame数据帧 2. 数据链路层 一个可靠的点对点数据直链。
    Bit比特 1. 物理层 一个(不一定可靠的)点对点数据直链。

    与之对应的是TCP/IP分层模型(TCP/IP Layening Model):
     

    4 应用层
    (OSI
    5到7层)
    例如HTTPFTPDNS
    (如BGPRIP这样的路由协议,尽管由于各种各样的原因它们分别运行在TCP和UDP上,仍然可以将它们看作网络层的一部分)
    3 传输层
    (OSI
    4层)
    例如TCPUDPRTPSCTP
    (如OSPF这样的路由协议,尽管运行在IP上也可以看作是网络层的一部分)
    2 网络互连层
    (OSI
    3层)
    对于TCP/IP来说这是因特网协议(IP)
    (如ICMPIGMP这样的必须协议尽管运行在IP上,也仍然可以看作是网络互连层的一部分;ARP不运行在IP上)
    1 网络接口层
    (OSI
    1和2层)
    例如以太网Wi-FiMPLS等。

    在OSI七层模型中,四层-Transport层的数据称作Segment,第三层IP层称作Packet,第二层链路层称作Frame。

    2、TCP Segment

          TCP首部报文格式:

    TCP Header
    OffsetsOctet0123
    OctetBit 0 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031
    00 Source port Destination port
    432 Sequence number
    864 Acknowledgment number (if ACK set)
    1296 Data offset Reserved
    0 0 0
    N
    S
    C
    W
    R
    E
    C
    E
    U
    R
    G
    A
    C
    K
    P
    S
    H
    R
    S
    T
    S
    Y
    N
    F
    I
    N
    Window Size
    16128 Checksum Urgent pointer (if URG set)
    20
    ...
    160
    ...
    Options (if data offset > 5. Padded at the end with "0" bytes if necessary.)
    ...

    首部结构中,

    • 四元组<src_ip, src_port, dst_ip, dst_port>共同确定了一条tcp连接,其中<src_ip, src_port> 、<dst_ip, dst_port>各组成一个socket.
    • Sequence Number是包的序号,新建一条连接时,SYN置1,Sequence Number初始化为ISR(initial sequence number),主机要发送的第一个字节编号为ISR+1,因为SYN消耗一个编号。Secquence Number用来解决网络包乱序(reordering)问题。
    • Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。ACK是发送端期望的下一个序号,因此ACK是收到的Secquence Number加1.
    • Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的
    • TCP Flag ,也就是包的类型,主要是用于操控TCP的状态机的

    3、TCP连接建立与释放

    TCP连接包括三个状态:连接创建、数据传送和连接终止,状态图:

          图 3-1. TCP的连接与释放

    3.1 建立连接

      在建立连接阶段,与上图对应的socket 原理图如下:

    1. 服务器准备好接受客户端的连接,通过socket, bind, listen三个函数实现,称为 被动打开(passive open)
    2. 客户端通过connect主动打开(active open),这导致TCP发送一个SYN同步分节,并通知服务器待建立的连接中client端的ISN,即上图中的J.
    3. 服务器对客户的SYN进行ACK确认,ACK=J+1。同时自己发送一个SYN分节,ISN为K.
    4. 客户端确认服务器的SYN, client回复的ACK=K+1.

    此时tcp连接已经建立,accept函数从连接队列中取出该连接并返回,client/server之间可以通过write/read收发数据。

    整个过程Server和Client之间有三次交互,称为三路握手(three-way handshake)。

    3.2 释放连接

        TCP连接是全双工的,每个方向都必须单独关闭,称为TCP的半关闭。因此终止TCP连接需要4次握手。

      

    1. 某个应用进程首先调用close, 称为主动关闭(active close), 该端发送FIN分节和seq=M。
    2. 收到这个分节的接收端执行被动关闭(passive close),被动端发送ACK=M+1回应并发送文件结束符(end-of-file)给应用进程。
    3. 一段时间后,收到end-of-file的进程调用close,发送FIN分节和seq=N。
    4. 主动关闭端收到FIN并回复ACK=N+1.

    至此,TCP连接释放。

    3.3 2MSL等待状态

      在主动关闭端TIME_WAIT状态到CLOSED状态,即发送最后一个ACK后,需要在TIME_WAIT状态等待2MSL时间。

    原因:TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到ACK,就会触发被动端重发FIN,一来一去正好2个MSL。

      2MSL状态的结果是,TCP连接在TIME_WAIT状态的2MSL时间内,socket不能被再次使用。大多数TCP实现(如BSD版等)加强了这个限制,在2MSL时间内,socket中的本地端口不能被重复使用,这主要会影响TCP服务器,因为服务器需要使用众所周知的端口号,而client只需由kernel分配一个端口即可。

      避开次限制的方法:SO_REUSEADDR选项, 

    opt = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    4、超时重传

      TCP提供可靠的运输层,方法之一就是确认从另一端发回的数据。当超过一定时间没有收到回复时,发送端重传数据。

    4.1、超时重传机制

      TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。

      接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?我们要知道,因为正如前面所说的,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。

      一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。

      但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。

    对此有两种选择:

    • 一种是仅重传timeout的包。也就是第3份数据。
    • 另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。

    这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长。

    4.2、快速重传机制

    于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。

    比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。示意图如下:

  • 相关阅读:
    控制一个cell不可被移动到另外一个section中
    core data 手动修改 .xcodatamodeld 文件 和 po 生成的 模型类 注意事项
    stringByTrimmingCharactersInSet 取出string 前后空格
    项目架构简述
    nil NULL [NSNULL null]
    如何定义一个应用之间调用的ios 本地URL
    UITableView隐藏多余的分割线
    解决UItableView cell的间隔线 separatorStyle ( plain group 两种类型)
    模拟器 真机 测试 内存消耗 资源对比
    微服务架构:Eureka集群搭建
  • 原文地址:https://www.cnblogs.com/ym65536/p/4309818.html
Copyright © 2020-2023  润新知