• 想进大厂?这些TCP协议知识你应该知道


    概念

    传输控制协议(TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,

    职责

    • 为进程和进程之间的通信,
    • 为进程间的通信提供可靠保证(并非安全保障)

    什么是可靠

    1. TCP会尽自己最大努力,将数据传输给对方
    2. 如果遇到实在无法发送不到的情况下,TCP会提示发送进程,数据发送操作失败了
    3. 保证不会收到错误的数据
    4. TCP能保证收到的数据一定是有序的(按照发送进程时的顺序)
    5. TCP会根据对方的接受能力和网络线路的承载能力,进行流量的控制

    TCP保证可靠的机制

    确认应答机制

    TCP将每个字节的书序都进行编号,即为序列号,每一个ACK都带有对应的确认序列号,告诉发送者,我已经收到了那些数据;下次你应该从哪里开始发。

    超时重传机制

    在上述通信过程中,主机A如果没有接收到主机B的应答会怎么办?可能是主机A在发送的途中丢包了,也有可能主机B回主机A的途中丢包了。

    • 主机A在给主机B发送数据的时候丢包了

    • 由于 TCP 是可靠的,丢包了他不会不管,主机A在接收主机B的应答时会等一段时间(估计数据到B的时间+B应答过来的时间),如果过了这段时间,还没有收到主机B的应答,那么主机A就认为丢包了,就会将刚才的数据重新发送一次,再等一段时间,如果收到应答了,继续通信,如果还是没等到应答,继续发送一次,发送好几次之后,如果还没收到应答,可能是网络太拥堵或者B那边出问题了,主机A关闭连接

    TCP会通过序列号做到去重的效果。 

    超时的时间是逐步增加的,一般都是第第一次发送的整数倍。

    超时重传的次数也是有上限的,达到上限后TCP会关闭本次连接、TCP会通知进程出现异常(通过抛出异常)、最后发送一个reset segment(重置报文)。

    连接管理机制

    三次握手

    第一次握手:建立连接时,客户端发送SYN包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认。

    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态。

    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

    SYN:同步序列编号

    四次挥手

    1. 第一次挥手:A->B,A向B发出释放连接请求的报文,其中FIN(终止位) = 1,seq(序列号)=u;在A发送完之后,A的TCP客户端进入FIN-WAIT-1(终止等待1)状态。此时A还是可以进行收数据的
    2. 第二次挥手:B->A:B在收到A的连接释放请求后,随即向A发送确认报文。其中ACK=1,seq=v,ack(确认号) = u +1;在B发送完毕后,B的服务器端进入CLOSE_WAIT(关闭等待)状态。此时A收到这个确认后就进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放的请求。此时B还是可以发数据的。
    3. (如果 B 直接跑路,则 A 永远处与这个状态。TCP 协议里面并没有对这个状态的处理,但 Linux 有,可以调整 tcp_fin_timeout 这个参数,设置一个超时时间。)
    4. 第三次挥手:B->A:当B已经没有要发送的数据时,B就会给A发送一个释放连接报文,其中FIN=1,ACK=1,seq=w,ack=u+1,在B发送完之后,B进入LAST-ACK(最后确认)状态。
    5. 第四次挥手:A->B;当A收到B的释放连接请求时,必须对此发出确认,其中ACK=1,seq=u+1,ack=w+1;A在发送完毕后,进入到TIME-WAIT (时间等待)状态。B在收到A的确认之后,进入到CLOSED(关闭)状态。在经过时间等待计时器设置的时间之后,A才会进入CLOSED状态。

    注意:客户端在发送完最后一次确认之后,还要等待2MSL的时间。主要有两个原因,一个是为了让B能够按照正常步骤进入CLOSED状态,二是为了防止已经失效的请求连接报文出现在下次连接中。

    TCP状态转换汇总图

     流量控制

      接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。 因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制。而滑动窗口机制可以用来实现接收端处理能力的判断。

    滑动窗口

    窗口的概念

    发送方的发送缓存内的数据都可以被分为4类:1. 已发送,已收到ACK2. 已发送,未收到ACK3. 未发送,但允许发送4. 未发送,但不允许发送

    其中类型2和3都属于发送窗口。

    接收方的缓存数据分为3类:1. 已接收2. 未接收但准备接收3. 未接收而且不准备接收

    其中类型2属于接收窗口。

    窗口大小代表了设备一次能从对端处理多少数据,之后再传给应用层。缓存传给应用层的数据不能是乱序的,窗口机制保证了这一点。现实中,应用层可能无法立刻从缓存中读取数据。

    滑动机制

    1. 发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
    2. 接收窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
    3. 遵循快速重传、累计确认、选择确认等规则。
    4. 发送方发的window size = 8192;就是接收端最多发送8192字节,这个8192一般就是发送方接收缓存的大小。

     

    拥塞控制

    虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大 量的数据,仍然可能引发问题。所以TCP引入了慢启动机制。

    慢启动机制

    • 先发送少量数据,试探当前网络的拥堵状态,再决定按照多大的速度传输数据。
    • 此处引入一个概念程为拥塞窗口
    • 发送开始的时候,定义拥塞窗口大小为1;
    • 每次收到一个ACK应答,拥塞窗口加1;
    • 每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为 实际发送的窗口;

    但是拥塞窗口的增长指数是指数级别,所以后期增长速度会趋于线性。

    • 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。
    • 此处引入一个叫做慢启动的阈值
    • 当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长

    •  当TCP开始启动的时候,慢启动阈值等于窗口最大值;
    • 在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;

    少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞;

    当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降; 拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的 折中方案。

  • 相关阅读:
    POI2020题解
    吃鸡达人必备:分享顶级干货+作图工具推荐+账号安全查询!
    create® 3入门教程-ROS2网络配置
    C/C++面试常见知识点
    Angular 项目升级需要注意什么?
    Sentinel 部署 配置
    [附源码]计算机毕业设计JAVAjsp智慧农产品朔源系统
    Git学习
    Python闯LeetCode--第2题:两数相加
    IO多路转接 —— 认识 poll 函数
  • 原文地址:https://blog.csdn.net/weixin_52206295/article/details/124903348