【JavaEE】TCP协议 (TCP-传输层协议 万字详解)

news2024/9/20 14:36:59

   🔥个人主页: 中草药

🔥专栏:【Java】登神长阶 史诗般的Java成神之路


🎤一.报头格式

        TCP (Transmission Control Protocol) 是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP 被设计用来提供端到端的数据传输服务,确保数据的完整性和顺序性。它是互联网协议族(Internet Protocol Suite)中的重要组成部分之一,在OSI七层模型中属于第四层,在TCP/IP四层模型中属于传输层。 

TCP 报头主要包括以下几个部分:

  • 源端口号:占用2字节,标识发送方的端口号。
  • 目的端口号:占用2字节,标识接收方的端口号。
  • 序列号:占用4字节,标识该TCP段中的第一个字节的序列号。
  • 确认号:占用4字节,标识期望接收的下一个字节的序列号。
  • 数据偏移:占用4位,指示TCP报头的长度(以32位即4字节为单位)。
  • 保留:占用6位,目前未使用。
  • 标志位:占用6位,包括URG、ACK、PSH、RST、SYN、FIN等标志。
  • 窗口大小:占用2字节,表示接收方的可用缓冲区大小。
  • 校验和:占用2字节,用于检测数据包中的错误。
  • 紧急指针:占用2字节,仅在URG标志置位时有效,表示紧急数据的末尾位置相对于序列号的位置。TCP在正常情况下都是按顺序来传输数据,紧急指针里面存的是一个偏移量,让后面的数据根据偏移量,把指定位置数据优先发送出去
  • 选项:可变长度,用于提供额外的功能,如窗口扩大因子、时间戳等。
  • 6位标志位:
  • URG: 与紧急指针配合使用
  • ACK: 确认号是否有效
  • PSH: 催促标志位,提示接收端应用程序立刻从TCP缓冲区把数据读走
  • RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
  • SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
  • FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
  • 16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.
  • 16位紧急指针: 标识哪部分数据是紧急数据;
  • 40字节头部选项: 暂时忽略;

🎧二.主要特点

  1. 面向连接:在数据传输前必须先建立连接,之后才能进行数据传输。连接的建立使用三次握手的过程,连接的终止使用四次挥手的过程。
  2. 可靠传输:通过序列号、确认应答、超时重传等机制来保证数据的可靠传输。
  3. 流量控制:使用滑动窗口机制来控制发送速率,避免发送方过快发送数据导致接收方来不及处理。
  4. 拥塞控制:通过慢启动、拥塞避免、快速重传和快速恢复等机制来避免网络拥塞。
  5. 差错控制:使用校验和来检测数据包中的错误,并通过重传来纠正错误。

🎼三.TCP状态

TCP状态机包括以下几种状态,这些状态按照一定的顺序变化,反映了TCP连接的不同阶段:

  1. CLOSED
  2. LISTEN
  3. SYN_SENT
  4. SYN_RECEIVED
  5. ESTABLISHED
  6. FIN_WAIT_1
  7. FIN_WAIT_2
  8. CLOSE_WAIT
  9. LAST_ACK
  10. CLOSING
  11. TIME_WAIT

详解

1. CLOSED

  • 描述:这是TCP连接的初始状态,表示没有任何连接活动。
  • 操作:当一个连接完全关闭后,进入此状态。

2. LISTEN

  • 描述:服务器处于监听状态,等待客户端的连接请求。
  • 操作:服务器调用listen()函数后,进入此状态。

3. SYN_SENT

  • 描述:客户端发送了一个SYN(同步)报文,请求建立连接。
  • 操作:客户端调用connect()函数后,发送SYN报文,并进入此状态。

4. SYN_RECEIVED

  • 描述:服务器收到了客户端的SYN报文,并发送了一个SYN+ACK(确认)报文作为响应。
  • 操作:服务器接收到客户端的SYN报文后,发送SYN+ACK报文,并进入此状态。

5. ESTABLISHED

  • 描述:连接已经建立,双方可以开始传输数据。
  • 操作:当客户端收到服务器的SYN+ACK报文后,发送一个ACK报文,连接建立完成,进入此状态。

6. FIN_WAIT_1

  • 描述:客户端发送了FIN(终止)报文,请求关闭连接。
  • 操作:客户端调用close()函数后,发送FIN报文,并进入此状态。
  • 备注:如果此时客户端还有未发送的数据,会先发送数据,然后再发送FIN报文。

7. FIN_WAIT_2

  • 描述:客户端收到了服务器的ACK报文,等待服务器发送FIN报文。
  • 操作:客户端发送FIN报文后,收到服务器的ACK报文,进入此状态。

8. CLOSE_WAIT

  • 描述:服务器收到了客户端的FIN报文,并发送了ACK报文,等待服务器自身的FIN报文。
  • 操作:服务器接收到客户端的FIN报文后,发送ACK报文,并进入此状态。
  • 备注:通常表示服务器还在处理一些数据或等待客户端发送更多的数据。

9. LAST_ACK

  • 描述:服务器发送了FIN报文,并等待客户端的ACK报文。
  • 操作:服务器在CLOSE_WAIT状态下发送FIN报文后,进入此状态。

10. CLOSING

  • 描述:客户端和服务器几乎同时发送FIN报文,进入此状态。
  • 操作:客户端发送FIN报文后,服务器也在同一时间发送FIN报文,双方都进入此状态。
  • 备注:这是一种很少见的状态,通常表示双方几乎同时发送了FIN报文。

11. TIME_WAIT

  • 描述:客户端收到了服务器的FIN报文,并发送了ACK报文,等待2MSL时间后关闭连接。
  • 操作:客户端接收到服务器的FIN报文后,发送ACK报文,并进入此状态。
  • 备注:2MSL(Maximum Segment Lifetime)是为了确保最后一个ACK报文能够被服务器收到,通常为2倍的平均往返时间(RTT)。

🎛️四.核心机制

核心机制 一:确认应答

        确认应答(ACK)是一种反馈机制,接收方通过发送 ACK 消息来告知发送方数据包是否成功接收。每个 TCP 数据包都有一个序列号(Sequence Number),表示该数据包的第一个字节的编号。接收方通过 ACK 字段发送一个确认号(Acknowledge Number),表示希望接收的下一个字节的序列号。

确认应答的工作原理

  1. 序列号与确认号

    • 序列号:每个 TCP 数据包都包含一个序列号,表示该数据包的第一个字节的编号。
    • 确认号:接收方通过 ACK 字段发送一个确认号,表示期望接收的下一个字节的序列号。
  2. 发送数据

    • 发送方向接收方发送一个数据包,其中包含数据和一个序列号。
    • 如果接收方成功接收到数据包,它会发送一个 ACK 消息,其中包含确认号,表示期望接收的下一个字节的序列号。
  3. 确认应答的发送时机

    • 每次接收到数据包时,接收方都会发送一个 ACK 消息。
    • 对于小的数据包,接收方可能采用累积确认(Cumulative Acknowledgment)的方式,即等到接收到多个数据包后再统一发送一个 ACK 消息。
    • 对于较大的数据包,接收方可能采用逐个确认的方式,即每接收到一个数据包就发送一个 ACK 消息。

优点

  1. 可靠性:确认应答机制确保了数据的可靠传输,避免了数据丢失。
  2. 顺序性:通过序列号和确认号机制,确保数据按顺序到达。
  3. 拥塞控制:确认应答机制配合其他拥塞控制机制,可以有效地避免网络拥塞。

局限性

  1. 延迟:确认应答机制增加了网络通信的延迟,尤其是在长距离或高丢包率的网络环境中。
  2. 资源消耗:频繁的确认应答会增加网络带宽和处理资源的消耗。

核心机制 二:超时重传

        重传机制是 TCP 用来处理数据包丢失的一种方法。当发送方发送数据后,如果没有在预期的时间内收到接收方的确认应答(ACK),就会认为数据包可能已经丢失,并重新发送该数据包。

工作原理(了解)

  1. 超时重传

    • 当发送方发送一个数据包后,会设置一个重传超时时间(Retransmission Timeout, RTO)。
    • 如果在 RTO 内没有收到接收方的 ACK,发送方就会重新发送该数据包。
    • RTO 的初始值通常是根据经验设定的,后续会根据实际网络条件动态调整。
  2. RTO 的计算

    • 平均往返时间(RTT):发送方通过测量从发送数据包到接收到 ACK 的时间来估计 RTT。
    • RTO 的计算公式:RTO = α × SRTT + (1 - α) × RTO
      • 其中,α 是平滑因子(通常为 0.125),SRTT 是平滑后的 RTT,RTO 是重传超时时间。
    • 估算 RTT:发送方维护一个样本 RTT(SampleRTT),并使用加权平均法更新 SRTT。
  3. 快速重传

    • 如果发送方在 RTO 到达之前收到了三个重复的 ACK(称为“三个重复 ACK 规则”),则认为中间的数据包丢失。
    • 发送方会立即重传丢失的数据包,而不必等待 RTO 超时。
    • 这种机制可以更快地检测到数据包丢失并及时重传,从而减少延迟。
  4. 选择性确认(SACK)

    • 选择性确认是 TCP 的一种扩展机制,允许接收方告诉发送方哪些数据段已经被成功接收。
    • 通过 SACK,发送方可以只重传那些真正丢失的数据段,而不是整个数据包。
    • 这种机制提高了效率,特别是在高丢包率的情况下。

优点

  1. 可靠性:重传机制确保数据包能够最终到达接收方,提高了传输的可靠性。
  2. 灵活性:通过快速重传和选择性确认机制,可以在高丢包率的网络环境中保持高效传输。
  3. 动态调整:RTO 的动态调整可以根据实际网络条件优化重传策略。

局限性

  1. 延迟:重传机制增加了网络通信的延迟,特别是在长距离或高丢包率的网络环境中。
  2. 资源消耗:频繁的重传会增加网络带宽和处理资源的消耗。
  3. 拥塞控制:重传机制需要与拥塞控制机制协同工作,避免因重传而导致网络拥塞加剧

核心机制 三:连接管理(三次握手,四次挥手)

  1. 连接建立

    • 三次握手:客户端发送一个带有SYN标志的TCP段到服务器,表示请求建立连接;服务器收到后发送一个带有SYN和ACK标志的TCP段回应客户端;客户端再次发送一个带有ACK标志的TCP段确认连接已建立。

三次握手的意义:

  1. 初步的验证通信的链路是否畅通,这是进行可靠传输的“前提条件”
  2. 确认通信的双方各自的发送能力和接受能力是否都正常
  3. 让通信双方在通信之前,协商通信过程中的关键参数,比如TCP连接的起始序号

三次握手之所以是三次,是中间的两次的交互合并在一起(中间的ACK+SYN,都是在内核之中,由操作系统负责进行的时机都是在SYN之后,此时为同一时机就合并了)

  1. 数据传输

    • 可靠传输:每个TCP段都包含一个序列号,用于标识该段中的第一个字节。接收方通过确认应答(ACK)来告诉发送方哪些数据已被成功接收。
    • 流量控制:使用滑动窗口机制来调整发送方的发送速率,避免发送速度过快导致接收方无法处理。
  2. 连接释放

    • 四次挥手:当一方发送完数据后,发送一个FIN标志的TCP段通知对方结束连接;另一方收到后发送ACK确认,并可能继续发送未发送完的数据;之后发送一个FIN标志的TCP段请求断开连接;最后,最初发送FIN的一方发送ACK确认连接断开。

“三次握手,四次挥手”详细图示(包括TCP状态转换) 

 核心机制 四:滑动窗口机制

滑动窗口机制允许接收方告知发送方它可以接收多少数据,从而控制发送方的数据发送速率。通过这种方式,接收方可以避免缓冲区溢出,同时保证数据的顺利接收。降低可靠性带来的性能损失

把多次等待ack的时间合并在一起 

掉包情况

无需特殊处理

批量发数据,批量的ack不会全丢,只丢一部分,后续的ack会弥补缺失的信息 

主机A在连续收到多个1001这样的ack之后,主机A会意识到1001的数据包丢失了,于是主机重传1001-2000   

当啊1001-2000重传过来之后,由于之前的2001-7000已经发过了,再弥补了空缺之后,接下来索要7001的数据包就好了

核心机制 五: 流量控制

        TCP(传输控制协议)中的流量控制机制是确保数据传输过程中不会导致接收方缓冲区溢出的重要机制。流量控制的主要目的是让发送方根据接收方的接收能力来调整数据的发送速率,从而避免数据丢失或拥塞。

        流量控制是指通过某种机制限制发送方的数据发送速率,以确保接收方能够及时处理接收到的数据。在TCP中,流量控制主要是通过滑动窗口(Sliding Window)机制来实现的。

过程

  • 接收端 将自己可以接受的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK端通知发送端
  • 接收端一旦发现自己的缓冲区快满了,将会把窗口大小设置成一个更小的值 通知给发送端,发送端在接受这个窗口后,就会减慢自己的发送速度
  • 接受端缓冲区满了,就会把窗口设置为0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段(不携带业务数据,只为触发ack)
  • 接收方也会在接收缓冲区不为0的时候,主动触发一个 窗口更新通知 的数据报

流量控制,站在接受方的视角来限制发送方的速度

拥塞控制,站在传输链路的视角来限制发送方的速度

核心机制 六: 拥塞控制

TCP(传输控制协议)中的拥塞控制机制是确保网络资源合理分配的关键技术之一。拥塞控制的目标是在网络拥塞时  减缓数据发送速率,避免过多的数据包在网络中堆积,从而导致网络性能下降或崩溃。TCP拥塞控制机制通过多种策略来实现这一目标,以下是拥塞控制机制的详细介绍。

  • 慢启动 刚开始发送数据,拥塞窗口会非常小,用一个很小的速度先发少量数据,探探路
  • 如果不丢包,增大窗口大小(指数增大)
  • 增长到一定程度,达到某个指定的阈值,即使,没有丢包,也会停止指数增删,变成 线性增长
  • 线性增长,也会使发送速度越快,达到某个速度,就会发生丢包
  • 一旦发生丢包,会回到一个新的ssthresh值,重新开始线性增长,形成动态平衡

优点

  1. 避免网络拥塞:通过动态调整发送速率,避免网络拥塞。
  2. 提高网络效率:通过快速重传和快速恢复机制,减少数据包丢失带来的延迟。
  3. 公平性:确保不同连接之间共享网络资源的公平性。

局限性

  1. 延迟:拥塞控制机制增加了网络通信的延迟,特别是在高延迟的网络环境中。
  2. 资源消耗:频繁的重传和调整发送速率会增加网络带宽和处理资源的消耗。
  3. 适应性:拥塞控制机制需要根据网络状况不断调整,对网络环境的变化适应性较强。

核心机制 七: 延迟应答

TCP(传输控制协议)中的延迟应答(Delayed Acknowledgment)机制是提高网络传输效率的一种策略。延迟应答机制允许接收方暂时不发送确认应答(ACK),而是等待一小段时间再发送,这样可以减少网络中的ACK报文数量,从而提高网络带宽的利用率。

并不是所有的包都可以延迟应答

  • 数量限制:每隔N个包应答一次
  • 时间限制:超过最大延迟时间就应答一次

具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms

 核心机制 八: 捎带应答

TCP(传输控制协议)中的捎带应答(Piggybacking Acknowledgments)是一种提高网络效率的技术,它允许接收方在发送数据时顺便携带确认应答(ACK)。这种方式减少了单独发送ACK报文的需求,从而降低了网络中的报文数量,提高了网络带宽的利用率。

 核心机制 九: 面向字节流

创建一个TCP的 socket ,同时在内核中创建一个 发送缓冲区 和一个 接受缓冲区

  • 调用write时,数据会先写入发送缓冲区
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出
  • 如果发送的字节数太短,就会放入缓冲区中等待,等到缓冲区长度差不多了,或者其他合适的时机
  • 接受数据时,数据也是从网卡驱动程序到达内核的接收缓冲区,然后应用程序可以调用read从接收缓冲区拿到
粘包问题
        粘包问题是TCP通信中常见的一个问题,尤其是在进行大量小数据包传输时。粘包问题指的是在网络传输过程中, 多个数据包在发送或接收时未能正确区分,导致数据包边界模糊不清,从而引起数据解析错误。下面详细讲解粘包问题的发生原因、影响以及解决方法。
粘包 粘的是 应用层数据包
解决方案
  • 引入分隔符,对于变长的包,可以指定明确的分隔符,只要不与正文冲突就好了(应用层协议)
  • 指定数据的长度,对于定长的包,保证每次按固定大小读取
  • 对于变长的包,可以在包头位置,约定一个包总长度的字段,从而告知包的结束位置

核心机制 十: 异常处理 

1.进程崩溃

        在java中的体现是在抛出异常之后,但是没有进行catch处理,最终异常进入到JVM里面,就会让JVM崩溃,在实际运行过程中,操作系统会对进行善后,在进程崩溃以后,进程中的PCB就要被回收,PCB中的文件描述符表里对应的所有文件,也都会被系统自动关闭,其中针对 socket 文件,也会触发正常的关闭流程(TCP的四次挥手)

PCB,全称为Process Control Block(进程控制块),是操作系统用来管理和控制进程运行的重要数据结构。每个进程在创建时都会由操作系统为其分配一个PCB,并在整个生命周期中维持这个结构的存在,直到进程终止。

2.主动关机

        在正常流程中执行关机操作,此时的操作系统会干掉所有的进程,同样会触发四次挥手,此时会有两种情况:

(a)四次挥手非常快,完成后,关机操作正式完成

(b)四次挥手还没有全部完成,就已经关机

 3.主动掉电

(a)接收方掉电

(b)发送方掉电 

如果发送探测报文后,A返回了ACK,说明A只是歇一歇,还为掉电,但是如果A没有ACK甚至说在多个探测报文后,A都没有ACK,此时的A就是掉电了

这样周期性的探测报文是用来探测对方的“生死”情况,这种的报文,称为心跳包

计算机中,非常广泛的使用 心跳包 的思想,TCP 内置了心跳包,由于 TCP 内置的心跳包周期比较长,秒级-分钟级应用程序这一层通常也会自行实现一些心跳包,达到更快速的"保活机制

4.网线断开


 🎚️六.示例代码

TCP客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket=null;

    public TcpEchoClient(String serverIP,int serverPort) throws IOException {
        socket=new Socket(serverIP,serverPort);
    }

    public void start(){
        System.out.println("客户端已启动");

        try(InputStream inputStream=socket.getInputStream();
            OutputStream outputStream=socket.getOutputStream()) {
            Scanner scanner=new Scanner(inputStream);
            Scanner sc=new Scanner(System.in);
            PrintWriter printWriter=new PrintWriter(outputStream);

            while(true){
                //1.从控制台读取数据
                System.out.print("->");
                String request=sc.next();

                //2.把请求发给服务器
                printWriter.println(request);
                printWriter.flush();

                //3.服务器读响应
                if(!scanner.hasNext()){
                    break;
                }
                String response=scanner.next();
                //打印日志
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient =new TcpEchoClient("127.0.0.1",9090);
        tcpEchoClient.start();

    }
}

TCP服务器

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Tcp 有连接 可靠传输 面向字节流 全双工
 */
public class TcpEchoServer {
    private ServerSocket serverSocket=null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException{
        System.out.println("启动服务器");
        while(true){
            Socket clientSocket =serverSocket.accept();
            /*
            线程池
            ExecutorService service= Executors.newCachedThreadPool();
            for (int i = 0; i < 1000; i++) {
                service.submit(()->{
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
             */

            Thread t=new Thread(()->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            t.start();
        }
    }

    private void processConnection(Socket clientSocket) throws IOException{
        //打印日志,客户端信息
        System.out.printf("[%s,%d]客户端已上线!",clientSocket.getInetAddress(),clientSocket.getPort());
        //获取socket中持有的流对象
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()){
        //为方便读取InputStream的请求,使用Scanner包装一下
            Scanner scanner=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);

            while(true){
                //1.读取请求并解析
                if (!scanner.hasNext()){
                    //如果用scanner也无法读出数据,则说明与客户端连接断开
                    break;
                    //跳出循环
                }
                String request = scanner.next();

                //2.根据请求计算请求
                String response=process(request);

                // 3. 把响应写回给客户端
                // 此处可以按照字节数组直接来写, 也可以有另外一种写法.
                // outputStream.write(response.getBytes());
                printWriter.println(response);
                //存在缓冲区,因此要 flush
                printWriter.flush();

                //4.打印日志
                System.out.printf("[%s,%d] req=%S resp=%s",clientSocket.getInetAddress(),clientSocket.getPort(),
                        request,response);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            System.out.printf("[%s,%d] 客户端已下线!",clientSocket.getInetAddress(),clientSocket.getPort());
            //要关闭资源
            clientSocket.close();
        }
    }

    private String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer=new TcpEchoServer(9090);
        tcpEchoServer.start();
    }
}

🧨五.总结与反思 

书的真正目的在于诱导头脑自己去思考。——莫利

TCP小结 

本篇文章主要讲了TCP协议的10个核心机制,或者说是常用机制,实际并不只有10个,TCP更多机制的详情请看 rcf标准文档

可靠性

  • 校验和
  • 序列号
  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制

提高性能

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

以下是 UDP 和 TCP 的对比总结,以表格的形式呈现:

特征TCP (Transmission Control Protocol)UDP (User Datagram Protocol)
类型面向连接无连接
可靠性可靠的不可靠的
顺序保证保证数据按顺序到达不保证数据顺序
流量控制使用滑动窗口机制没有流量控制机制
拥塞控制动态调整发送速率以避免网络拥塞没有拥塞控制
数据传输单元数据报 (Datagram)
重传机制有,使用超时和重传没有重传机制
确认应答有,通过ACK确认收到数据没有确认应答
头部开销20字节(基本)8字节
广播/多播支持不支持多播支持广播和多播
应用场景Web浏览(HTTP/HTTPS),文件传输(FTP),邮件传输(SMTP)等实时音频/视频(VoIP,直播),DNS查询,多人在线游戏等
优点高可靠性,保证数据顺序,拥塞控制低延迟,简单,适合实时应用
缺点较高的开销,较慢的速度数据包可能丢失或乱序

UDP和TCP 两个协议并没有优劣之分

TCP 对于数据需要可靠传输的场景,必然是首选

UDP 对于可靠性要求不高,对于性能要求很高的场景

解释:

  • 面向连接 vs 无连接:TCP 在数据传输之前需要建立连接,而 UDP 则不需要。
  • 可靠性:TCP 通过序列号、确认应答和重传来确保数据的可靠传输,而 UDP 不提供这些机制。
  • 顺序保证:TCP 确保数据包按顺序到达,而 UDP 不保证数据包的顺序。
  • 流量控制:TCP 使用滑动窗口机制来控制数据发送的速率,而 UDP 没有流量控制机制。
  • 拥塞控制:TCP 通过慢启动、拥塞避免、快速重传和快速恢复等机制来避免网络拥塞,而 UDP 没有拥塞控制。
  • 数据传输单元:TCP 是面向字节流的,而 UDP 是面向数据报的。
  • 重传机制:TCP 在数据丢失时会进行重传,而 UDP 不会。
  • 确认应答:TCP 使用 ACK 来确认数据包是否被接收,而 UDP 不使用确认应答。
  • 头部开销:TCP 的头部至少为20字节,而 UDP 的头部为8字节。
  • 广播/多播支持:UDP 支持广播和多播,而 TCP 不支持。
  • 应用场景:TCP 适用于对可靠性要求较高的应用,如Web浏览、文件传输等;而 UDP 更适合实时应用,如在线游戏、视频流等。
  • 优点和缺点:TCP 的优点在于高可靠性,但也有较高的开销和较慢的速度;UDP 的优点在于低延迟和简单性,但数据包可能丢失或乱序。

🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀

以上,就是本期的全部内容啦,若有错误疏忽希望各位大佬及时指出💐

  制作不易,希望能对各位提供微小的帮助,可否留下你免费的赞呢🌸

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2123244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Brequinar (Synonyms: 布喹那; DUP785; NSC 368390) AbMole介绍

Brequinar&#xff08;布喹那&#xff09;是一种合成的喹啉羧酸类似物&#xff0c;也是有效的二氢乳清酸脱氢酶(DHODH)抑制剂&#xff0c;对人 的 IC50 值为 5.2 nM&#xff0c;可以通过抑制DHODH&#xff0c;从而阻断嘧啶的从头合成。此外&#xff0c;Brequinar还可诱导肿瘤的…

【kafka】消息队列

本文主要通过字节的团队的博客学习kafka&#xff0c;写的真不错&#xff1a;一键跳转 1.kafka的架构 2.kafka的副本管理 3.日志同步管理 4.kafka快的原因&#xff1f; 批量处理、消息压缩、建立索引、分区、一致性、顺序写盘、页缓存、0拷贝 5.kafka怎么保证可靠&#xff1f…

【C++ Qt day10】

2、 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&am…

OCR在线识别网站现已上线!

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 由作者亲自开发的ocr识别网站哈哈,暂时汇聚了三十多种验证码模型以及算法,欢迎各路朋友去尝试,网站地址如下 http://gbj5w3.natappfree.cc/ocr 验证码类型包括但…

【MADRL】反事实多智能体策略梯度法(COMA)算法

本篇文章是博主强化学习RL领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在强化学习专栏&#xff1…

前端开发的观察者模式

什么是观察者设计模式 观察者模式&#xff08;Observer Pattern&#xff09;是前端开发中常用的一种设计模式。它定义了一种一对多的依赖关系&#xff0c;使得当一个对象的状态发生改变时&#xff0c;其所有依赖对象都能收到通知并自动更新。观察者模式广泛应用于事件驱动的系…

56页PPT | 大数据决策分析平台怎么建设?经典实践方案推荐

一、现状和目标 企业用户现状&#xff1a;数据分散&#xff0c;利用率低&#xff0c;业务需求变化快但IT响应慢。 问题&#xff1a;数据展示不及时、不准确&#xff0c;缺乏深入分析工具&#xff0c;报表制作效率低下。 目标&#xff1a;建设统一的数据整合平台&#xff0c;…

四款数据恢复精灵好用之处及使用感受~

在数字化的时代&#xff0c;数据的重要性不言而喻&#xff1b;不慎删除重要文件、格式化磁盘后数据丢失、存储设备故障……这些情况都可能让我们痛心疾首&#xff1b;这时&#xff0c;数据恢复软件就显得尤为重要了&#xff0c;今天&#xff0c;就为大家介绍四款备受好评的数据…

服装|基于Java+vue的服装定制系统(源码+数据库+文档)

服装定制系统 目录 基于Javavue的服装定制系统 一、前言 二、系统设计 三、系统功能设计 系统功能实现 管理员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布…

Linux——redis主从复制、集群模式、哨兵模式

主从复制 部署至少两个redis的实例 // 提供数据冗余和备份 两个独立服务器两个虚拟机两个容器一个redis的master 节点可以有多个redis的replica 从节点&#xff0c; 而从节点也可以成为其他从节点的主节点 // 方便对于主复制架构进行扩展提供数据灾备&#xff0c;当red…

复赛总榜TOP1方案Champion Chasing Boy分享

关联比赛: 2020数字中国创新大赛—算法赛&#xff1a;智慧海洋建设 写在前面的话 大家好&#xff0c;我是 Champion Chasing Boy的DOTA&#xff0c;在队友 鱼遇雨欲语与余、 尘沙杰少、林有夕、嗯哼哼唧 的Carry下&#xff0c;最终在本届智能算法赛拿到了复赛总榜单Top1的成绩…

Java通过jna调用c++动态库

1、pom文件添加jna依赖 <dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.14.0</version></dependency> 2、注意问题 要实现Java调用C的动态库&#xff0c;需要使用"extern C&…

Script-server: 一款开源的脚本管理工具,为你的Python脚本提供一个直观的 Web UI

在日常工作中&#xff0c;我们经常会使用各种脚本来自动化任务&#xff0c;提升效率。但传统的脚本管理方式往往伴随着一些困扰&#xff1a;复杂的命令行操作、难以理解的脚本参数、缺乏直观的反馈等等。这些问题&#xff0c;让原本应该便捷的脚本管理变得繁琐。 Script-server…

Qt-QWidget的focusPolicy属性(20)

目录 描述 相关API 使用 描述 这里引入了焦点的概念&#xff0c;这个很重要&#xff0c;也是伴随后面介绍中的一个很重要的概念 拿魔兽世界来举例&#xff0c;如下我们在操作兵种的时候&#xff0c;需要先选中单位&#xff0c;然后才能对这些单位进行命令的下达 这一点在笔…

[极客大挑战 2019]Http

1、访问题目链接 2、查看页面源码发现一个Secret.php的跳转页面 3、访问Secret.php发现页面有提示&#xff0c;它说它不是来自这个网页 4、抓包修改来源 添加&#xff1a;Referer: https://Sycsecret.buuoj.cn 发送查看响应 5、修改User-Agent为&#xff1a;Syclover 6、添加X-…

Catia的插件不能调用CAA 的API问题

今天到客户实施Catia二开软件&#xff0c;发现在客户的电脑上调用CAA的API出现调用失败的问题。 根据经验&#xff0c;想到大概是用户电脑上的Catia授权有问题&#xff0c;但是Catia的一大堆授权中需要哪些授权呢&#xff0c;最后花了半天的时间使用二分法测试出&#xff0c;C…

产线工控安全之防勒索病毒杀手锏

在当今数字化时代&#xff0c;数据安全已成为企业运营中不可或缺的一部分。勒索病毒和内部泄密事件的频发&#xff0c;使得企业必须采取更为严格的安全措施来保护其关键数据和运营系统。苏州深信达网络科技推出的MCK主机加固解决方案&#xff0c;正是为了应对这些挑战而设计的。…

十三、创建Uss血条样式

一、控制StyleSheet 1、点击左上角USS文件&#xff08;创建&#xff09; 2、双击style里面的黄色progress-bar 3、在USS文件夹中添加代码实现 4、在主UI上有一个margin&#xff08;外&#xff09;和padding(里) 在Spacing中进行修改 5、只有文字可以在这里进行修改 6、在Atrib…

车载以太网之SOME/IP

整体介绍 SOME/IP(全称为:Scalable service-Oriented MiddlewarE over IP),是运行在车载以太网协议栈基础之上的中间件,或者也可以称为应用层软件。 ​发展历程 AUTOSAR 4.0 - 完成宝马SOME/IP消息的初步集成;AUTOSAR 4.1 - 支持SOME/IP-SD及其发布/订阅功能;AUTOSAR 4.…

自动驾驶相关的理论基础

本文主要参考论文《基于计算机视觉和深度学习的自动驾驶方法研究_白辰甲》&#xff0c;记录一些理论知识。 自动驾驶定义 自动驾驶是指车辆通过传感器感知周围环境&#xff0c;在没有人为干预的情况下&#xff0c;实时改变驾驶行为&#xff0c;完成驾驶任务。 基于计算机视觉…