当前位置: 首页 > news >正文

计算机网络-----详解网络原理TCP/IP(上)

文章目录

    • 📕1. UDP协议
        • ✏️1.1 UDP的特点
        • ✏️1.2 基于UDP的应用层协议
    • 📕2. TCP协议
        • ✏️2.1 TCP协议段格式
        • ✏️2.2 TCP协议特点之确认应答
        • ✏️2.3 TCP协议特点之超时重传
        • ✏️2.4 TCP协议特点之连接管理
        • ✏️2.5 TCP协议特点之滑动窗口
        • ✏️2.6 TCP协议特点之流量控制
        • ✏️2.7 TCP协议特点之拥塞控制
        • ✏️2.8 TCP协议特点之延迟应答
        • ✏️2.9 TCP协议特点之捎带应答
        • ✏️2.10 TCP协议特点之面向字节流(重点粘包问题)
        • ✏️2.11 TCP协议特点之异常情况
    • 🌈六个标志位总结

📕1. UDP协议

在这里插入图片描述

  1. 16位UDP长度 : 表示整个数据报(UDP首部+UDP数据)的最大长度 . 我们注意到, UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部). 然而64K在当今的互联网环境下, 是一个非常小的数字.如果我们需要传输的数据超过64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装;
  2. 16位UDP校验和 : 主要作用是验证UDP数据报在传输中是否出错(数据在传输过程中 , 会发生比特反转 , 导致数据出错) , 发送方发送数据时构造数据报 , 构造完数据报后, 将数据报每个字节的数据都进行相加 , 结果累加到一个16位的整数上(溢出也无所谓) , 最终的结果就是校验和(check1) , 填充到UDP报头的校验和字段 , 当接收方接收到数据后 , 也会利用相同算法算出一个校验和check2 , 如果check1==check2 , 就认为传输的数据是正确的 , 如果不相等 , 就认为数据出错了 .
✏️1.1 UDP的特点
  1. 无连接 : 知道对端的IP和端口号就可以直接就行传输 , 不需要进行连接(可以和TCP的连接管理特点进行相对比)
  2. 不可靠 : 没有确认机制 , 重传机制 . 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息
  3. 面向数据报 : 无法灵活的控制读写数据的次数和数量 (无论应用层交给UDP多长的报文 , UDP既不会拆分 , 也不会合并 , 因为UDP最大长度只有64kb , 超过64kb就需要我们在应用层手动拆分 , 很低效)
✏️1.2 基于UDP的应用层协议
  1. NFS: 网络文件系统
  2. TFTP: 简单文件传输协议
  3. DHCP: 动态主机配置协议
  4. BOOTP: 启动协议(用于无盘设备启动)
  5. DNS: 域名解析协议

📕2. TCP协议

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

✏️2.1 TCP协议段格式

在这里插入图片描述

  1. 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去;

  2. 32位序号/32位确认号 : 详情请查阅TCP协议特点之确认应答

  3. 4位首部长度 : TCP报头中包含可选项 , 所以最大长度有60字节

  4. 6位标志位 :
    ◦ URG: 紧急指针是否有效
    ◦ ACK: 确认号是否有效
    ◦ PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
    ◦ RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
    ◦ SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
    ◦ FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段

  5. 16位窗口大小 : 详情请查阅TCP协议特点之滑动窗口

  6. 16位紧急指针 : 标识哪部分数据是紧急数据;

  7. 16位校验和 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.

  8. 40字节头部选项 : 暂时忽略;

✏️2.2 TCP协议特点之确认应答

首先我们要明确一点 , 确认应答机制是为了让TCP协议实现可靠传输 , 发送方发送信息给接收方 , 如果接收方收到了 , 就向发送方返回一个应答报文(acknowledge)“我已收到” , 这便是确认应答的核心策略 , 如果没有返回应答报文 , 发送方便会认为刚刚发送的数据包发生了丢包 , 会立刻采取补救措施.

正常情况下的确认应答
在这里插入图片描述
但是 , 在网络中 , 可能会出现"后发先至"现象 , 因为在网络中 , 数据包会经过无数台路由交换器 , 有的网络线路通畅 , 有的网络线路拥塞 , 就会产生"后发先至"现象
在这里插入图片描述
这样 , 以我的视角来看 , 针对吃饭这事 , 小芳子让我滚 , 但是 , 小芳子愿意做我女朋友 , 这就出现了严重的BUG

为了解决上述问题 , TCP协议引入了序号与确认序号
在这里插入图片描述
在这里插入图片描述
TCP为每个字节的数据都编了序号 , 我们只需知道第一个字节的序号即可 , 后续序号依次递增 , 确认序号只在应答报文中生效 , 当ACK标志位为1的时候 , 就是应答报文 .
在这里插入图片描述
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.

确认序号的意义 :

  1. 所有<确认序号的信息 , 接收方都已经收到了
  2. 发送方接下来 , 应该从确认序号位置 , 继续发送数据
✏️2.3 TCP协议特点之超时重传

通过确认应答 , 我们可以知道数据包到没到达接收方 , 但在实际情况中 , 很可能会丢包 , 超时重传是去确认应答的补充 , 主要针对丢包的场景 , 其中超时是判断是否丢包的条件 , 如果发现数据丢包 , 就重新传一次 , 在计算机中 , 不喜欢无限的等 , 如果超出最大等待时间还没收到ACK , 就会被认为丢包了 , 在不同系统上 , 最大等待时间不同.

关于没收到ACK的情况 , 有以下两种 :
在这里插入图片描述
主机A长时间没有收到主机B的ACK , 就会认为丢包 , 重新传输数据包 , 但是, 同一份数据包主机A传输多次后 , 主机B怎么知道是否已经处理了这个数据包呢?这就利用到了刚刚的序号与确认序号 , TCP在接收数据时 , 会在操作系统内核维护着一个"数据缓冲区" , 如果收到了相同的数据就会根据数据的序号在数据缓冲区中进行去重 , 确保在进行read操作读的数据不会重复.

那么 , 超时的时间该如何确认呢?TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.如果重发一次之后, 仍然得不到应答, 等待 2500ms 后再进行重传.如果仍然得不到应答, 等待 4500ms 进行重传. 依次类推, 以指数形式递增.但是重传次数和总的重传时间是有上限的 , 达到上限还没有重传成功 , TCP就会被重置(单方面断开连接) , 触发一个RST复位报文 , 意味着就不要这个连接了 , 这是一个单方面的通知 , 释放连接就是要删除之前保留的对方信息.

✏️2.4 TCP协议特点之连接管理

此处我们所说的连接 , 是虚拟的连接 , 是指通信双方各自保存对方的信息(IP , 端口号等) , 我们通常采用三次握手建立连接 , 四次挥手断开连接 .

  1. 三次握手建立连接

TCP中的握手 , 传输的是一个"打招呼"的数据包 , 这个数据包不携带任何"业务数据". 三次握手关键流程请看下图 :
在这里插入图片描述

  1. 发送方向接收方发起一个syn(同步报文段) , 告诉接收方 , 我要和你建立连接 .
  2. 接收方给发送方返回一个ack , 告诉发送方我已收到 , 我会保存你的信息
  3. 接收方向发送方发起一个syn(同步报文段) , 告诉发送方我也想和你建立连接
  4. 发送方给接收方返回一个ack , 告诉接收方我已收到 , 我也保存你的信息

可是 , 我们不是说好的是三次握手吗?这怎么是四次了呢?

从逻辑上来看是四次交互 , 但是中间两次 , 可以合并成一个数据包 , 网络上实际只传输了三个数据包 , 返回ack和syn都是内核控制的 , 和程序代码无关(程序员干预不了) , 操作系统可以再同一时间返回ack和syn数据包 , 因此我们称它为三次握手建立连接.
在这里插入图片描述
那三次握手的意义是什么呢?可以解决什么问题呢?

三次握手 , 可以视为保证可靠传输的辅助手段 , 真正保证可靠传输的是我们上面介绍的确认应答和超时重传.

  1. 三次握手 , 相当于"投石问路" , 验证通信链路是否通畅
  2. 三次握手 , 也验证了通信双方发送能力和接受能力是否正常
  3. 通过三次握手 , 让双方协商出关键信息(例如TCP数据的其实编号 , 因为传输的数据包第一个字节的编号并不是从0/1开始排的 , 而是三次握手协商出来的)

TCP状态变化图
在这里插入图片描述

LISTEN : 服务器存在的状态 , 服务器new ServerSocket就会进入到LISTEN状态 , 表示在监听这个端口 ,端口上过来客户端 , 就能accept了

ESTABLISHED : 服务端和客户端连接建立好了 , 客户端和服务端可以进行通信了

  1. 四次挥手断开连接

四次挥手断开连接 , 有可能是客户端发起 , 也有可能是服务端发起 , 而三次握手建立连接 , 一定是客户端发起的

在这里插入图片描述

  1. 客户端告诉服务端 , 我要和你断开连接
  2. 立刻返回ACK , 表示收到
  3. 服务端告诉客户端我也要和你断开连接
  4. 客户端返回ACK , 表示收到(然后客户端和服务端都会把之前保留的对方信息全部删掉)

之所以叫做四次挥手断开连接 , 是因为中间两次不一定会合并 , 当客户端返回ACK时 , 此时服务端会执行业务代码 , 这个业务代码是由程序员编写的 , 具体时间因业务逻辑而定 , 如果时间较长 , FIN和ACK就无法一起返回 , 如果时间比较短 , 或者通过延时应答机制 , 就可以优化成FIN和ACK一起返回 , 合并比不合并效率要高 , 毕竟封装拆用都是要消耗系统资源的 , 举个简单例子 , 我在淘宝买一件短袖 , 我下单后店家就会立刻打包联系快递 , 如果快递没发走之前 , 我又下单了一件短袖 , 这样商家就会把两件短袖打包成一个快递发走 , 如果第一件短袖已经到了快递中转站 , 则第二件短袖就必须重新联系快递 , 这样就会增大开销 . 合并是四次挥手的特殊优化手段 , 所以我们还还把断开连接称为四次挥手断开连接

在这里插入图片描述
四次挥手的意义就是为了"释放空间"

CLOSE_WAIT : 当服务器收到客户端发来的FIN , 立刻返回ACK , 服务器就会进入CLOSE_WAIT状态 , 等待服务器执行完业务代码调用close()关闭.
TIME_WAIT : 等待连接彻底释放 , 我方发送FIN , 对方返回ACK , 对方返回FIN , 我方发送ACK , 此时就应该断开连接 , 但是会先进入TIME_WAIT状态 , 并不会直接断开连接. 如果最后一个ACK丢包 , 那么服务端重传的FIN就无人受理 , 如果较长时间没有收到重传的FIN , 就认为服务端收到了最后一个ACK , 就可以断开链接了 , 等待的时间大多数2*MSL(网络上任意两点 , 最大传输时间)

在这里插入图片描述

✏️2.5 TCP协议特点之滑动窗口

上述我们介绍的三个机制 , 都是为了保证TCP传输数据的可靠性 , 但是每发一个数据都要等待ACK , 单位时间传输的数据就会减少 , 而滑动窗口 , 主要的目的就是为了提高效率的

在这里插入图片描述
既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了).

在这里插入图片描述

  1. 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是4000个字节(四个段).
  2. 发送前四个段的时候, 不需要等待任何ACK, 直接发送;
  3. 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推;
  4. 操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
  5. 窗口越大, 则网络的吞吐率就越高;

在这里插入图片描述

每次收到一个ACK , 窗口都会往后平移一个格子 , 如果收到的ACK速度很快 , 平移的过程就像"滑动"的过程.

那么滑动窗口情况下发生丢包怎么处理呢?可以分为两种情况

  1. 数据包已经到达 , 返回的ACK被丢了
    在这里插入图片描述
    如果只是ACK丢包 , 在滑动窗口机制下 , 则不需要处理 , 因为ACK确认序号的规则是所有小于确认序号的数据包都已经成功收到了 , 例如1001 , 2001 , 3001 , ACK都丢包了 , 但返回的5001ACK没有丢包 , 则客户端认为服务端已经收到了5001前所有的数据.(我们的人生轨迹大多是上大学 , 找工作 , 谈恋爱 , 结婚 , 生孩子 , 如果有一天某人问我是否单身吗 , 我回答他说我孩子都上小学了 , 那是不是就意味着我不单身了呢?)

  2. 数据包直接丢了

在这里插入图片描述
此时1001-2000数据包丢了 , 主机B就会重复向主机A索要1001数据包 , A感知到之后 , 就会知道1001数据包丢失 , 就会立刻重传 , 一旦B收到了1001数据包 , 而且B观察数据缓冲区里已经有2001-7001数据了 , 就会返回索要7001的ACK应答报文(这种机制我们也可以成为快速重传)

接下来又有一个疑问?那最后一个ACK丢包了怎么办?最后一条数据怎么呢?

实际上快速重传和超时重传并不冲突 , 当最后一条ACK客户端没收到的话 , 客户端还会采用超时重传机制

✏️2.6 TCP协议特点之流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等⼀系列连锁反应. 流量控制(Flow Control)就是搭配滑动窗口 , 根据接收方的处理能力 , 干预发送方的发送速度(调整滑动窗口大小)
在这里插入图片描述
发送方发送的数据 , 会先进入接收方的接收缓冲区(类似于阻塞队列 , 队列里没有数据 , 应用程序read时就会阻塞) , 所谓接收方的处理能力 , 就是从缓冲区read数据的速度 , 这个速度适合业务逻辑代码相关的(与程序员强相关) , 所以并不是很好测量 , 所以我们采用另一个指标来判断read速度的大小
在这里插入图片描述
在接收方返回ACK报文时 , 会把接收缓冲区剩余容量位置大小放在TCP 首部中的 “窗口大小” 字段返回给发送方 , 这样发送方在下一次发送数据的时候就会调整窗口大小 , 窗口大小字段越大, 说明网络的吞吐量越高 , 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端 , 发送端接受到这个窗口之后, 就会减慢自己的发送速度;

那么问题来了 , 窗口大小只有16位 , 最大只能是64kb吗? 非也 , TCP设计的时候充分吸收了UDP的经验 , 在选项中有一个"窗口扩展因子M"选项 , 实际窗口大小是窗口字段的值左移 M 位;

在这里插入图片描述

✏️2.7 TCP协议特点之拥塞控制

虽然TCP有了滑动窗⼝这个⼤杀器,能够⾼效可靠的发送⼤量的数据,但是如果在刚开始阶段就发送⼤量的数据,仍然可能引发问题,发送方的速率不光要考虑接收方的速率,还要考虑传输路径整个过程中的所有节点的情况,拥塞(se四声)控制的作用就是限制滑动窗口的发送速度,以防发送速度超过传输路径中的最小传输速度(木桶效应)。
在这里插入图片描述

拥塞控制的核心思路的就是“试试看”,先按照比较小的速率发送一个数据包试一试,不丢包的就增大发送速率,如果出现丢包了就减小发送速率(就是一个动态平衡的效果,水多加面,面多加水),发送方的发送窗口大小同时取决于流量控制和拥塞控制,谁小就用谁

拥塞窗口大小也是比较巧妙的设定,TCP引⼊慢启动机制, 先发少量的数据, 探探路, 摸清当前的⽹络拥堵状态, 再决定按照多⼤的速度传数据。

在这里插入图片描述

  1. 初始情况下拥塞窗口的大小是非常非常小的,因为刚开始,网络的状畅通情况是未知的。
  2. 慢启动情况下如果不丢包,拥塞窗口大小就会成指数级别增大,快速将拥塞窗口大小调大(因为最开始慢启动拥塞窗口大小实在是太小了)
  3. 指数增长达到一定程度(达到阈值),就会成线性增长(主要怕指数增长某一次增长好多,超出上限好多,最理想的状态就是擦着上限的边进行传输)
  4. 线性增长到上限终究会出现丢包
  5. (TCP Tahoe版本 已废弃) 出现丢包后,窗口大小一落千丈,重新开始慢启动,改变指数增长的阈值,重新进行指数增长,线性增长过程
  6. (TCP Reno版本) 出现丢包后,重新计算阈值(丢包的窗口大小/2),从新的阈值作为窗口大小,继续线性增长
✏️2.8 TCP协议特点之延迟应答

我们为了提升传输速率,要在保证安全性的前提下,尽可能的增加滑动窗口的大小,如果接受方收到数据包后立刻返回ack,那返回的剩余数据缓冲区大小可能就会很小。假设接收端缓冲区为1M,⼀次收到了500K的数据, 如果⽴刻应答, 返回的窗⼝就是500K,但实际上可能处理速度会很快,这样就可以稍微等一等(目的是为让接受缓冲区的剩余容量在大一些)在返回ack,这样返回的窗口大小还是1M。

举一个学生时期的例子:高中的时候每当我们放月假,老师总会留很多卷子,假期结束的那个晚自习让课代表收上去。可是既然放假了,我又怎么可能会写卷子呢,假设老师一共留了10张卷子,课代表收卷子的时候我告诉明天早上我再给你,我利用一个晚自习就能补完5张,那么第二天,老师只能骂我为什么作业只写了一半,而不会说我为什么一点作业都不写,这就是延迟应答。(从实际效果来看,延迟应答非常有作用!!!)

✏️2.9 TCP协议特点之捎带应答

在网络通信中,经常是一问一答模型,客户端发起请求,服务端返回响应。服务端返回的ACK是接收到客户端的请求后立即返回的,而响应具体的返回时间不确定,是有应用层代码所决定的,但是因为TCP有延迟应答的特点,如果延迟应答返回ACK的时间和服务器返回响应的时间相差不大的情况下,返回ACK的同时就会把响应一起返回客户端,这就是捎带应答策略,捎带应答是基于延迟应答的基础上,提高传输效率的方案。捎带应答即取决于延迟应答,又取决于应用程序的处理逻辑,并不是100%会触发的。
在这里插入图片描述
举一个小小的例子:我是一个非常懒的人,我在床上躺着时候突然口渴想喝水了,但是我又不愿意动,于是我就没有喝,又突然我想去上厕所了,我就可以趁着上厕所的机会把水喝了,本来需要下两次床,现在下一次床就可以了。

✏️2.10 TCP协议特点之面向字节流(重点粘包问题)

每当我们创建一个TCP的socket时,就会在系统内核中创建一个发送缓冲区与接受缓冲区,调用write时,会先写入发送缓冲区,如果发送的字节数太长,就会被自动拆成多个数据包发出,如果发送的字节数太短,就会先在发送缓冲区等待,等到足够长了在发送出去。接受数据时,应用程序也是从接收缓冲区read数据,另⼀⽅⾯, TCP的⼀个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这⼀个连接, 既可以读数据,也可以写数据. 这个概念叫做全双⼯。由于缓冲区的存在,读写和写入操作就有很多种,变得非常灵活,例如写入100字节时,可以一次写100字节,也可以写10次,一次写10字节,读取的时候也同理,这也是TCP的一个重要特点----面向字节流。

粘包问题

当我们有以下发送数据包情景时 :
在这里插入图片描述
接受方收到后,去掉报头,将数据放在接收缓冲区中:
在这里插入图片描述

此时接受方的应用程序read时就有很多种可能:

  1. aaab bb ccc
  2. aa abbb ccc
  3. a aabb bccc

具体哪一种读法是对的呢?这就是粘包问题:粘包,粘的是应用层的数据包,因为TCP字节流的特性,收多个数据包都会放在接收缓冲区中,因为包与包的边界比较模糊,无法区分哪些字节是独立的包,就会造成读取上的错误。

那么该如何解决粘包问题呢?解决粘包问题的本质是区分包与包之间的边界,属于我们写代码时要特别注意的点。

  1. 通过特殊的分隔符,来区分包与包之间的边界,例如:约定包都以分号作为结尾。
  2. 在应用层数据包开头的位置,通过固定长度,来约定应用层数据包的长度。
    在这里插入图片描述
    在这里插入图片描述
    应用层read的时候,先固定read2个字节,如果下一次读到的是3,就读三个字节,就能读到了aaa完整的数据包

粘包问题只针对于字节流传输,对于文件操作,也有可能会遇见粘包问题。

✏️2.11 TCP协议特点之异常情况
  1. 进程终止(正常流程)

只要是进程终止,都会释放PCB,释放文件描述符,触发FIN。

  1. 主机关机(正常流程)

正常流程下的主机关机,就会先杀死所有进程,触发四次挥手断开连接
如果关机的速度比较慢,很有可能四次挥手就挥完了
如果关机的速度比较快,刚发完FIN就关机了,此时对端会返回ack,也会发送一个fin,因为我方已经关机了,无法返回ack,对方会多次发送fin,如果都没有收到ack,对端直接放弃连接(删除之前保留的信息)
四次挥手,挥完了,双方删除对方信息,没挥完,至少自己可以删除对方信息,不用管对方(对方已经关机所有数据也都没了)。

  1. 主机掉电(直接拔电源)

如果掉电的一方是接受方:对方发送数据,接受方没有返回ack,发送方会超时重传,达到一定程度还没有ack,发送方会发送一个复位报文,表示要单方面放弃当前的连接。

如果掉电的一方是发送方:接受方感受到的是发送方突然停下了,接受方会阻塞等待,等待发送方发送新的数据,但并不是无期限的等,接受方会周期性的交换心跳包(这个机制非常重要,尤其是在分布式系统中,各个服务器就是通过心跳包来感知对方的存活与否),如果接受方感知不到对方的心跳包了,就可以单方面释放连接了。

  1. 网线断开

流程与主机掉电一模一样,也区分断开的是发送方还是接受方,不再过多赘述

🌈六个标志位总结

最后的最后,总结一下TCP协议中的6个标识位
在这里插入图片描述

谨以此文 纪念我的计算机网络求学之路 此致 2025.6.16 凌晨1.01 于大连

相关文章:

  • 定制PyTorch后端通信(backend)实战
  • MCP终极指南 - 番外篇:抓包分析 Cline 与模型的交互协议
  • ollama常见属性设置
  • AIGC 使用层 | 关于AI prompt
  • Spring常用的注解详细介绍 原理分析,与实际案例
  • 黑客是如何攻击一部手机的?
  • Objective-C与Swift混合编程
  • 使用SVN checkout时报错Unable to connect to a repository at URL
  • LINUX616 问题:vim编辑器;粘滞位(其他需回顾);配置静态网络报错;more,less,head命令
  • 如何确定驱动480x320分辨率的显示屏所需的MCU主频
  • 微信小程序页面容器弹出层
  • Next.js面试题:API深度解析
  • LangChain 与 Milvus 的碰撞:全文检索技术实践
  • java 设计模式_行为型_23状态模式
  • 论文笔记:CAN LLMS UNDERSTAND TIME SERIES ANOMALIES?
  • Kafka Connect实战:从环境搭建到全流程操作
  • solana 编写智能合约 然后调用它
  • C#/.NET/.NET Core技术前沿周刊 | 第 42 期(2025年6.9-6.15)
  • Debian 编译安装 ruby3.2
  • webpack到vite的改造之路
  • 教育考试类网站建设/查域名
  • 网上兼职网站开发/短视频seo推广
  • 影响网站显示度的原因/百度网盘怎么找资源
  • 有梦商城公司网站/怎么做推广网站
  • 国内界面优秀的网站/外贸谷歌优化
  • 16岁的做兼职在什么网站好/百度网盘资源搜索引擎入口