【Linux】TCP全解析:构建可靠的网络通信桥梁

文章目录

  • 前言
  • 1. TCP 协议概述
  • 2. TCP报头结构
  • 3. 如何理解封装和解包呢?
  • 4. TCP的可靠性机制
    • 4.1 TCP的确认应答机制
  • 4.2 超时重传机制
  • 5. TCP链接管理机制
    • 5.1 经典面试题:为什么建立连接是三次握手?
    • 5.2 经典面试题:为什么要进行四次挥手?
  • 6. 流量控制
  • 7. 滑动窗口机制
  • 8. 拥塞控制
  • 9. 面向字节流的特性
  • 10. 粘包问题及解决方案
  • 11. TCP异常情况处理
  • 12. TCP 小结
  • 13. TCP与UDP的对比
  • 14. 用 UDP 实现可靠传输(经典面试题)
  • 总结

前言

在计算机网络中,传输层协议扮演着至关重要的角色,它们负责在网络中的主机之间可靠地传输数据。其中,TCP(传输控制协议)和UDP(用户数据报协议)是最常见的两种传输层协议。TCP以其可靠性、有序性和流量控制等特性,成为了许多关键应用的首选协议,如文件传输、电子邮件、Web 服务等。然而,TCP的复杂性和性能开销也使得它在某些场景下不如UDP灵活和高效。本文将深入探讨TCP协议的各个方面,从其基本机制到高级特性,再到与UDP的对比,帮助读者全面理解TCP的工作原理和应用场景。

1. TCP 协议概述

TCP 全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制;

2. TCP报头结构

在这里插入图片描述
在这里插入图片描述

一眼看去, TCP协议确实比UDP要复杂的多, TCP协议的报头并不是定长的, 你可能会发现它除了选项和数据的长度是定长的20字节。但是它的选项的长度是不定的. 在前20字节中有一个叫4位首部长度的字段。它代表了报头一共有多大, 范围是: 20~60字节

TCP报头的其他字段数据, 比如: 序号, 确认序号, 窗口大小, 6位标志位等. 就是TCP用来保证它的效率和可靠性时需要使用到的字段

3. 如何理解封装和解包呢?

  1. OS内可不可以同时存在很多个收到的报文,这个报文还没来得及处理,甚至拷贝到传输层的接收缓冲区,甚至没有交给传输层而在网络层和链路层。
  2. OS内一定会收到大量还没来得及处理的报文,OS要不要对大量的暂未处理,但以及接收到的报文进行管理呢?要!(先描述,再组织)

添加报头只需要将head指针向左移动(封装的过程就是指针移动+填写报头)
解包就是将head指针强转,再提取他的字段,之后将head指针向又移动。
在这里插入图片描述

  • 封装和解包,在内核中,只需要进行指针移动即可!

4. TCP的可靠性机制

4.1 TCP的确认应答机制

TCP 保证可靠性!
确认应答保证历史消息被收到了,可靠性是对历史消息的可靠性的一种保证!
确认应答机制:
在这里插入图片描述

  • 比如主机A给主机B发送了1000字节的数据, 那么这个TCP包中的序号就为1000. 当B主机收到TCP包后, 会给A主机发送确认应答, 并且会将确认序号设置为1001, 代表1001以前的数据我都收到了. 可以从1001个字节开始给我发数据了。
  • 同理,要是B主机没有给A发送1001确认序号,而是直接发送了2001. 证明2001以前的数据都收到了, 包括1~1000的
  • tcp 发送消息的模式 ——version0
    发送数据和发送应答,一般是是 双方OS自动完成的!(通信细节OS自动解决了!)

  • tcp 发送消息的模式 ——version1
    根据发送报文的顺序进行排序,根据序号,进行tcp的按序到达!
    在这里插入图片描述

  • 32位的确认序号:收到的序号 + 1 (该确认序号之前的数据,我已经全部收到了,下次发送,请从确认序号开始!)

在这里插入图片描述

既想做确认应答,又想发数据!这种方式叫做捎带应答!(既是应答,又携带了数据!)

  • 序号存在的意义:按序到达,应答和确认应答
  • 确认序号&&序号:同时向双方发送数据的同时,也同时在做应答
  • 为什么tcp报头中要有标志位?标志位存在的意义?
    :需要区分不同的报文请求!即区分不同的报文类型!
    我们的server一定在通信的过程中,会同时收到各种各样的报文!(即TCP报文是需要类型的!)

在这里插入图片描述

为什么发SYN其实只是SYN被置1了,发送不同的请求只需要将不同的标记位置1即可!
其中三次握手由OS自动完成! 用户只用使用connect进行发起。
如何进行连接?管理,先描述,再组织!(内核数据结构,内存空间和时间)
维护连接是有成本的!时空成本

在这里插入图片描述

断开链接时,双方各自向对方提出断开的要求,然后再断开链接 close(fd) (四次挥手)

在这里插入图片描述

确认应答(ACK)机制,是报证可靠性的最基础也是最重要的一种机制!

在这里插入图片描述

4.2 超时重传机制

没有收到应答呢?
需要去等,等多长时间呢?
约定,对方没有收到报文,在一个时间端内,没有收到应答

数据丢包:
在这里插入图片描述
应答丢包:
在这里插入图片描述
在这里插入图片描述

5. TCP链接管理机制

正常的情况下,TCP要经过三次握手建立连接四次挥手断开连接
在这里插入图片描述

像SYN、ACK这些是标记位,我们发送过去的是完整的TCP报头,并不是只是这些标志位!
connect(fd,服务器地址端口) 发起了三次握手,accept返回不参与三次握手!
三次握手与四次挥手都是操作系统自己完成的!

  • **三次握手:**不是能100%建立好链接,而是经历三次握手,c/s都是认为连接建立好了

  • RST(reset):重置!
    所谓的链接重置,就是让两方,重新进行三次握手!
    解决的问题就是连接出现异常的问题!

5.1 经典面试题:为什么建立连接是三次握手?

为什么不进行一次或两次连接,因为这样有明显漏洞,客户端不用应答就可以不停的去连接,这样只用一台客户端就可以对服务器工具(SYN洪水),而三次握手呢,客户端也需要建立连接,这样就不会受到单机的攻击!

三次握手
理由一:需要保重信道(网络)是健康的
三次握手,CS双方,都会有确定的一次收发,CS确认全双工

理由二:确保双方OS(TCP)是健康且愿意通信的(建立了通信的共识)。
服务端回应的时候进行捎带应答,表达了服务器急切的情绪!
三次握手的本质就是四次握手,只不过中间两次被捎带应答了!

5.2 经典面试题:为什么要进行四次挥手?

在思想上三次握手和四次挥手没有区别。

CLOSE_WAIT, TIME_WAIT
如果我们发现我们的服务器上有大量的close_wait状态的时候,这意味着,大概率我们的服务器有bug,主要是没有close_fd

  • TIME_WAIT: 等待一定的时长

  • 为什么要等?

1.保证历史的报文有足够的时间进行消散,保证一来一回的时间。
2. 在我们四次挥手的过程中,看起来最后一个ACK没有应答,但其实这个ACK是有应答的,因为它还会发送FIN,如果最后一个客户端没有收到,服务器不可能走到LAST_ACK,等的时候同样会响应FIN,如果等待的时间内ACK没丢那么响应的这么长时间内那么就不会收到另一个FIN了!TIME_WAIT保证了对方的ACK也能顺利完成!(还有重传的机会)

  • 时长是多长呢?

等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态

6. 流量控制

在这里插入图片描述

主机A发的太快了,主机B来不及接收
主机B可以向主机A通告自己的接收能力
什么叫主机B的接收能力?我的接收缓冲区中剩余空间的大小!
怎么通告?主机B有确认应答机制(在自己的ACK报文中,填写自己的16位窗口大小)

  • 具体流量控制
    接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应.
    因此 TCP 支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);
  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过 ACK 端通知发送端;
  • 窗口大小字段越大, 说明网络的吞吐量越高;
  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度;
  • 如果接收端缓冲区满了, 就会将窗口置为 0; 这时发送方不再发送数据, 但是需
  • 要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.

在这里插入图片描述
设置PSH标志位,催促B主机快点发送窗口大小
UGR:紧急指针,让B主机优先处理

7. 滑动窗口机制

解决主机之间发送效率低下的问题,实现并行发送!
在这里插入图片描述
滑动窗口的大小:不考虑网络的情况,滑动窗口大小一般是:对方缓冲区中剩余空间的大小(暂时)

滑动窗口是发送缓冲区的一部分
报头中的窗口大小描述的是接收方的发送能力,滑动窗口的大小表示的是发送方的发送能力的问题

在这里插入图片描述

  1. 超时重传?

对发送的报文,并且没有收到的应答的报文进行保存(在滑动窗口中),方便我们经行重传!

  1. 如何理解这个滑动窗口呢?

a.只能向右滑动吗? 只能向右滑动
b.可以变大吗?可以变小吗? 可以
c.可以为0吗?可以

  1. 理解它?

滑动窗口的本质其实就是两个整型变量维护的一段数组空间

在这里插入图片描述
收到ACK报文,应答报头中的窗口大小,表面对方的接收能力 win
变更滑动窗口
在这里插入图片描述
- 确认序号的意义:确认序号之前的报文全部收到了!

丢包:
快重传策略:必须收到3个同样的确认应答则进行重发。

  1. 最左侧丢包:滑动窗口不能进行右移!(我们不担心最左侧报文丢失,会对丢失的报文进行快重传与超时重传策略)
  2. 中间报文丢失:右滑转换为最左侧丢包问题
  3. 最右侧报文丢包:右划转换为最左侧丢包问题
    在滑动窗口内,所有的问题全部会转换成为最左侧丢包问题!

流量控制是如何做到的?

滑动窗口在滑动的过程中既可以变大也可以变小,也可以为0,滑动窗口的大小要和对方的接收窗口吻合,滑动窗口的大小暂时等于对方的接收能力。这样保证了既可以保证以最高的速率全力发送,又可以防止对方的数据进行溢出多发,即保证发送速率又保证接收能力。
滑动窗口是流量控制的具体实现,是重传策略的具体实现。

缓冲区是一个类似于环状队列所以不用担心数据的溢出

8. 拥塞控制

虽然 TCP 有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题.因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据, 是很有可能引起雪上加霜的.
TCP 引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据;

网络出现大面积丢包,说明网络拥塞了!
在这里插入图片描述

一但发生网络拥塞,识别到的网络拥塞主机全部要进行拥塞控制。

滑动窗口 == min(接收方的窗口(接收能力),拥塞窗口)

2^n -> 慢启动,拥塞控制的核心算法?
在这里插入图片描述
探测网络的健康状态:
在这里插入图片描述

  • ssthresh值:阈值,记录上一次拥塞窗口值(32位)的一半,作为下一次窗口变化的临界值,指数增长变为线性增长!

9. 面向字节流的特性

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

  • 调用 write 时, 数据会先写入发送缓冲区中;
  • 如果发送的字节数太长, 会被拆分成多个 TCP 的数据包发出;
  • 如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区长度差不多了, 或者其他合适的时机发送出去;
  • 接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区;
  • 然后应用程序可以调用 read 从接收缓冲区拿数据;
  • 另一方面, TCP 的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工

由于缓冲区的存在, TCP 程序的读和写不需要一一匹配, 例如:

  • 写 100 个字节数据时, 可以调用一次 write 写 100 个字节, 也可以调用 100 次write, 每次写一个字节;
  • 读 100 个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100 个字节, 也可以一次 read 一个字节, 重复 100 次;

10. 粘包问题及解决方案

  • 先要明确, 粘包问题中的 “包” , 是指的应用层的数据包.
  • 在 TCP 的协议头中, 没有如同 UDP 一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段.
  • 站在传输层的角度, TCP 是一个一个报文过来的. 按照序号排好序放在缓冲区中.
  • 站在应用层的角度, 看到的只是一串连续的字节数据.
  • 那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.

那么如何避免粘包问题呢? 归根结底就是一句话, 明确两个包之间的边界.

  • 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的 Request 结构, 是固定大小的, 那么就从缓冲区从头开始按 sizeof(Request)依次读取即可;
  • 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
  • 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只要保证分隔符不和正文冲突即可);

思考: 对于 UDP 协议来说, 是否也存在 “粘包问题” 呢?

  • 对于 UDP, 如果还没有上层交付数据, UDP 的报文长度仍然在. 同时, UDP 是一个一个把数据交付给应用层. 就有很明确的数据边界.
  • 站在应用层的站在应用层的角度, 使用 UDP 的时候, 要么收到完整的 UDP 报文, 要么不收. 不会出现"半个"的情况

11. TCP异常情况处理

进程终止: 进程终止会释放文件描述符, 仍然可以发送 FIN. 和正常关闭没有什么区别.
机器重启: 和进程终止的情况相同.
机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行 reset. 即使没有写入操作, TCP 自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
另外, 应用层的某些协议, 也有一些这样的检测机制. 例如 HTTP 长连接中,

12. TCP 小结

为什么 TCP 这么复杂? 因为要保证可靠性, 同时又尽可能的提高性能!
可靠性:

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

提高性能:

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

其他:

  • 定时器(超时重传定时器, 保活定时器, TIME_WAIT 定时器等)

基于 TCP 应用层

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP

当然, 也包括你自己写 TCP 程序时自定义的应用层协

13. TCP与UDP的对比

我们说了 TCP 是可靠连接, 那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点, 不能简单, 绝对的进行比较

  • TCP 用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;
  • UDP 用于对高速传输和实时性要求较高的通信领域, 例如, 早期的 QQ, 视频传输等. 另外 UDP 可以用于广播

归根结底, TCP 和 UDP 都是程序员的工具, 什么时机用, 具体怎么用, 还是要根据具体的需求场景去判定.

14. 用 UDP 实现可靠传输(经典面试题)

参考 TCP 的可靠性机制, 在应用层实现类似的逻辑;

例如:

  • 引入序列号, 保证数据顺序;
  • 引入确认应答, 确保对端收到了数据;
  • 引入超时重传, 如果隔一段时间没有应答, 就重发数据;

总结

经过对TCP协议的全面分析,我们可以得出以下结论:

  1. 可靠性:TCP通过序列号、确认应答、超时重传、连接管理、流量控制和拥塞控制等机制,确保数据的可靠传输。这些机制虽然增加了协议的复杂性,但也大大提高了数据传输的可靠性。

  2. 性能:尽管TCP的可靠性机制带来了一定的性能开销,但通过滑动窗口、快速重传、延迟应答和捎带应答等技术,TCP能够在保证可靠性的同时,尽可能地提高传输效率。

  3. 应用场景:TCP适用于需要可靠传输的应用,如文件传输、电子邮件、Web 服务等。而UDP则适用于对实时性和传输速度要求较高的应用,如视频传输、在线游戏等。

  4. 与UDP的对比:TCP和UDP各有优缺点,选择哪种协议取决于具体的应用需求。TCP提供了更可靠的传输保障,但可能会牺牲一些性能;UDP则在传输速度和实时性方面表现更优,但传输的可靠性较低。

  5. 实现可靠传输:即使在UDP这样的不可靠协议上,也可以通过应用层的逻辑实现类似TCP的可靠性机制,如序列号、确认应答和超时重传等。

通过本文的学习,读者应该能够更深入地理解TCP协议的工作原理,掌握其关键特性,并能够根据实际需求选择合适的传输层协议。希望本文能够为读者在网络编程和应用开发中提供有价值的参考。

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

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

相关文章

Java每日一题 ~ 盛最多水的容器

. - 力扣(LeetCode) 1.题目解析 本题的要求就是:给定数组索引之间的差值为宽,元素值中小的为边长求面积。 2.算法分析 思路一:暴力枚举 暴力法的思路是对所有可能的容器组合进行穷举,计算它们能容纳的水…

[硬件]—电感传感器

电感传感器 1.概述 工作基础:电磁感应,即利用线圈自感或互感的改变来实现非电量测量。工作原理: 被测物理量(非电量:位移、振动、流量);线圈自感系数L/互感系数M;电压或电流&#…

0729作业+梳理

一、作业 1.写一个日志文件&#xff0c;将程序启动后的每一秒时间写入到文件中 代码&#xff1a; #include<myhead.h> #include<time.h> //判断原本文件中的行数 int len_txt(FILE *fp) { char buf0; int count 1; while(1) { buffgetc…

计算是守恒与对称的,谋算(算计)是变通与破缺的

计算通常涉及到严格的数学或逻辑规则&#xff0c;这些规则保证了信息或量的守恒和对称性。例如&#xff0c;数学运算如加减乘除都遵循特定的规律&#xff0c;确保了结果的准确性和一致性。相比之下&#xff0c;谋算&#xff08;或称算计&#xff09;更多指策略性的考虑或具有权…

Redis 缓存中间件

目录 概念 安装redis redis基本命令 给redis添加密码 基础数据类型 string类型 list列表类型 set创建&#xff08;一个键对应一个值&#xff09; set 创建数据 get 获取数据 keys * 展示所有的键 exists 判断键值是否存在 type 查看数据的类型 del 删除键 rename…

学习008-02-04-03 Group List View Data(组列表查看数据)

Group List View Data&#xff08;组列表查看数据&#xff09; This lesson explains how to group the Employee List View data by department and position. 本课介绍如何按部门和职位对员工列表视图数据进行分组。 Note Before you proceed, take a moment to review the …

机械学习—零基础学习日志(高数15——函数极限性质)

零基础为了学人工智能&#xff0c;真的开始复习高数 这里我们将会学习函数极限的性质。 唯一性 来一个练习题&#xff1a; 再来一个练习&#xff1a; 这里我问了一下ChatGPT&#xff0c;如果一个值两侧分别趋近于正无穷&#xff0c;以及负无穷。理论上这个极限值应该说是不存…

2024下《系统架构设计师》案例简答题,刷这些就够了!

2024年软考下半年已经越来越近了&#xff0c;不知道今年备考架构的同学们准备得怎么样了呢&#xff1f; 简答题一直是架构拿分的重点区域&#xff0c;对于许多考生来说&#xff0c;也往往是最具挑战性的部分。今天我就把那些重要的案例简答题类型整理汇总给大家&#xff0c;希望…

02 Go语言操作MySQL基础教程_20240729 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 Golang零基础入门Golang面向对象编程Go Web 基础Go语言开发REST API接口_20240728 基础不好的同学每节课的代码最好配合视频进行阅读和学习&#xff0c;如果基础比较扎实&#xff0c;则阅读本教程巩固一下相…

Qt Designer,仿作一个ui界面的练习(二):部件内容的填充

有了完成了布局的基本框架设计之后&#xff0c;对各个部件逐步完成内容的填充。 一、还是从顶边栏开始&#xff1a; 1、在顶边栏的topLogo里面拖入一个QLabel&#xff08;标签&#xff09;&#xff0c;命名为logoImage&#xff0c;删除标签的文字。 2、右键点击topLogo&#x…

计算机三级嵌入式(三)——嵌入式系统硬件组成

目录 考点1 嵌入式最小硬件系统 考点2 基于 ARM 内核的典型嵌入式应用系统硬件组成 考点3 ARM 的 AMBA 总线体系结构及标准 考点4 基于 ARM 内核的嵌入式芯片的硬件组成 考点5 存储器层次结构 考点6 存储器分类 考点7 存储器主要性能指标 考点8 片内存储器 考点9 外部…

IndexError: list index out of range

IndexError: list index out of range 目录 IndexError: list index out of range 【常见模块错误】 【解决方案】 原因分析 解决方法 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身…

接口自动化中对于文件上传的处理方法

正常的接口自动化基本都是json的格式&#xff0c;对于文件上传是一种特殊的格式是表单格式针对这种表单格式在接口自动化中怎么处理&#xff0c;主要通过工作中使用的一个实际的例子进行分享 举例&#xff1a;web上需要导入一个文件实现相关的功能&#xff0c;主要通过两个接口…

C语言玩一下标准输出——颜色、闪烁、加粗、下划线属性

文章目录 C语言玩一下标准输出——颜色、闪烁、加粗、下划线属性转换Tip切换内容介绍显示方式字体色背景色 常用光标控制附示例和运行结果 C语言玩一下标准输出——颜色、闪烁、加粗、下划线属性 标准输出格式其属性可控制&#xff0c;控制由一系列的控制码指定。标准输出函数可…

这才是 PHP 高性能框架 Workerman 的立命之本

大家好&#xff0c;我是码农先森。 在这个大家都崇尚高性能的时代&#xff0c;程序员的谈笑间句句都离不开高性能&#xff0c;仿佛嘴角边不挂着「高性能」三个字都会显得自己很 Low&#xff0c;其中众所皆知的 Nginx 就是高性能的代表。有些朋友可能连什么是高性能都不一定理解…

C++11 列表初始化与类型声明

目录 ​ 0.前言 1.C11介绍 2.统一的列表初始化 2.1{}初始化 2.2initializer_list 2.2.1initializer_list 的基本用法 2.2.2用于类的 initializer_list 构造函数 2.2.3与标准库容器的结合 2.2.4优势与注意事项 3.新声明 3.1auto 3.1.1基本用法 3.1.2优势 3.1.3注意事项 3.2declt…

npm国内淘宝镜像registry镜像过期

我们在使用npm的时候会遇到淘宝镜像安装过期的问题 首先了解 npm 淘宝镜像是一个 npm 注册表的镜像&#xff0c;用于加速 npm 包的下载。 一、如何设置&#xff1f; 如何设置淘宝镜像&#xff1f;淘宝镜像已经从 registry.npm.taobao.org 切换到了 registry.npmmirror.com n…

贪吃蛇 C++简易版(完整代码)

代码&#xff1a; #include <iostream> #include <conio.h> #include <vector> #include <windows.h> #include <ctime>using namespace std; //设置范围 const int WIDTH 20; const int HEIGHT 20;const char EMPTY ; const char SNAKE O…

代码随想录总结

文章目录 1. 回溯法1.1 组合1.2 组合总和31.3 电话号码的字母组合 2. 1. 回溯法 经典问题&#xff1a;排列、组合、切割、子集、棋盘 void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择&#xff1a;本层集合中元素&#xff08;树中节点孩子的数量就是集合的…

【SpringBoot教程:从入门到精通】掌握Springboot开发技巧和窍门(四)-Vue项目配置环境、导航栏

主要写前端页面&#xff0c;采用vue框架写页面的导航栏&#xff01;&#xff01;&#xff01; 文章目录 前言 Vue项目配置环境 安装依赖 创建菜单 总结 前言 主要写前端页面&#xff0c;采用vue框架写页面的导航栏&#xff01;&#xff01;&#xff01; Vue项目配置环境 安装…