本文收录于「流浪」的系列专栏Linux系统⚙️C数据结构与算法PythonLangChain LangGraph️MySQL 数据库Git 工具计算机网络LLM大厂面试、八股学习筑基专栏 博客主页流浪 原创首发于 CSDN前言《计算机网络篇14》把 UDP 的 8 字节定长报头拆完TCP 的报头是另一副样子20 字节起步后面还能挂可变选项。本篇先拆 4 位首部长度怎么把报头和有效载荷分开、TCP 为什么没有长度字段再顺着可靠性往下走确认应答为什么不必再被应答、并发发送怎么逼出序号、全双工又为什么要求两个独立的序号字段。一、TCP 报头与有效载荷的分离1.1 20 字节固定报头加可变选项16 位端口号负责交付1. TCP 报头由固定部分加选项构成TCP 报头是「20 字节固定长度 选项」的组合固定部分每条报文都有、格式永远不变选项部分可长可短、可有可无这和 《计算机网络篇14》里 UDP 那种 8 字节一次定死的报头不是一种设计——UDP 把长度写死在协议里TCP 把长度做成了可调的代价随之而来UDP 靠定长就能切出报头和载荷TCP 必须自己回答一个问题这条报文的报头到底到哪里结束2. 交付由 16 位目的端口号完成报文跨过网络到达主机后传输层从报头里取出 16 位目的端口号把有效载荷交到对应进程的手上这套两级查表在 《计算机网络篇3》里走过完整的流程「交给谁」由端口号解决「从哪开始算载荷」就是另一个问题了——报头和有效载荷怎么分离得有一个字段来管端口号解决交付首部长度解决分离TCP 报头里每个字段背后都压着这样一个具体的问题。1.2 4 位首部长度撑起最多 60 字节的可变报头1. 4 位字段的天然上限是 15 个单位负责分离的字段叫 4 位首部长度在 RFC 里叫数据偏移Data Offset只有 4 个比特取值范围 [0000, 1111]也就是 [0, 15]如果按 1 字节为单位理解它能声明的报头长度最多 15 字节——可 TCP 光固定部分就有 20 字节[0, 15] 连下限都盖不住4 个比特撑不起 20 字节起步的报头这不是字段设计失误而是基本单位还没定对2. 协议把基本单位定成 4 字节TCP 规定发送方和接收方在计算首部长度时以 4 字节为基本单位字段里的数值是多少报头就占多少个 4 字节换算回字节4 位的上限 15 对应 15×4 60 字节报头长度范围一下子扩成了 [0, 60]固定的 20 字节是每条报文必有的部分折成单位是 20÷4 5所以字段实际取值 [5, 15]报头实际长度范围 [20, 60]3. 选项长度从首部长度里倒推出来报头总长减去固定 20 字节剩下的就是选项的空间选项长度范围 0 到 40 字节选项是 TCP 给自己留的扩展和协商参数的余地具体哪个选项对应哪个机制讲到对应机制时自然会碰到报头能伸能缩的范围全在一个 4 位字段里声明完单位放大到 4 字节15 个单位封顶 605 个单位打底 20。1.3 分离的判定按首部长度读满为止1. 首部长度之前是报头之后全是载荷接收方拿到报文按首部长度字段读满对应字节数读掉的这部分按报头格式逐一解释剩下的从头到尾都是有效载荷选项部分因为同样被首部长度覆盖解析时不会和载荷混淆——不管选项带了几个字节都在「读满为止」的那一段里面UDP 靠定长免掉了这个字段TCP 靠字段补上了可变长两条路通向同一个目的让接收方不用猜定长把分离规则写进协议可变长把分离规则写进字段TCP 选了后一条路换来的是报头可以按需伸缩。二、TCP 报头没有长度字段字节流没有边界2.1 UDP 的长度字段在 TCP 报头里找不到对应物1. UDP 用 16 位长度记录整条报文《计算机网络篇14》里拆过UDP 报头的 16 位长度字段记录的是整条数据报的长度首部加数据一把全算有这个字段在OS 处理 UDP 时能明确区分每条报文的边界——整条多长读满就完2. TCP 报头里没有 TCP 长度同样的字段在 TCP 报头里找不到TCP 没有「TCP 长度」这个东西也就是说仅凭 TCP 报文自身OS 说不出这条报文的数据部分到底有多长2.2 面向字节流OS 不能真实区分每次传输的长度1. TCP 眼里只有一串连续字节TCP 是面向字节流的协议交付的单位不是「一条条报文」而是一串没有边界的字节——《计算机网络篇8》讲报文边界时正面撞过这件事应用层一次 write 交下来的数据TCP 可能拆成几段发出去也可能攒着和别的数据合着发每一段和用户的一次写入之间不再一一对应所以 OS 不能真实区分「每一次 TCP 传输」的长度——不是它懒得记是这串字节本来就没有「每一次」这个划分2. 两个协议对长度的态度对照维度UDPTCP报头长度8 字节定长20 字节起步[20, 60] 可变长度字段16 位长度记整条报文没有对应字段边界归属协议层保留报文边界边界交回应用层自己切OS 区分边界能不能只有字节流UDP 的长度字段保住的是报文边界TCP 没这个字段是因为它压根不打算保留边界——字节流和长度字段一个存在就宣判了另一个不存在。三、确认应答机制应答本身不需要再被应答3.1 C 发消息、S 作应答以及「应答谁来确认」1. C 发消息、S 作应答这是最粗略的通信样貌站在 C 端和 S 端来讲C 发消息给 SS 收到后给 C 一个应答——这一来一回就是确认应答Acknowledgment机制最粗略的样子S 给出应答这个动作代表 S 确实收到了 C 的消息这一层没有歧义2. 但 S 不确定自己的应答 C 有没有收到应答也是一条报文同样可能丢、可能没送到——S 发出应答之后并不知道 C 收没收到它那要不要让 C 再补一条告诉 S「你的应答我收到了」3. 若继续确认下去循环停不下来让 C 补一条「应答已收到」这条新报文立刻变成新的待确认消息轮到 S 来确认它收到没有S 补一条「确认已收到」这条又轮到 C 来确认……每补一层刚发出去的那层就又变成待确认的确认链永远差一层才能收尾谁也说不清哪一条才算最后一句通信没有终点这不是实现上的取舍问题是规则本身的结构问题——只要「每条消息都必须被确认」这个规则在循环就必然出现3.2 裁决不对应用答作应答1. TCP 把整个循环裁掉确认应答机制只做一层收到消息就应答但对「应答」本身不再作应答两个方向同理——S 给 C 发消息时 C 作应答S 不对 C 的这条应答再作应答谁收到数据谁应答应答本身免检2. 免检不产生漏洞的原因C 收到 S 的应答这件事本身就说明C 之前发给 S 的消息S 已经收到并且处理过了——确认消息被收到是捎在「C 继续往下通信」这个动作里的换句话说应答到达的那一刻它要确认的事已经成立给应答再配一个应答只是把已经成立的事实重复一遍停止确认循环可靠性一分没少报文的数量却不用无限叠加应答不需要被应答是因为应答到达时它所确认的事实已经成立确认链在一层处截断是确认应答机制能落地的前提。3.3 可靠性的边界历史可靠最新悬空1. 有应答保证的是历史消息已经拿到应答的那些消息可靠性是有保证的——应答就是接收方亲口承认「收到了」通信持续进行绝大部分消息都会沉淀成历史消息被一个个应答逐条锁定2. 最新报文永远没有应答通信中最新发出的那条报文永远处在「还没有应答」的状态——它的应答要么在路上要么还没发出所以严格说确认应答机制保证的从来不是「所有消息都可靠」而是「除了最新的那条其余全部可靠」——最新消息的可靠性无法保证这是这套机制的天然边界确认应答的可靠性画到最新报文为止历史消息被逐条锁定最新一条永远悬在「等确认」的位置上。四、从串行等待到并发发送4.1 收到应答再发下一条效率太慢1. 串行的速度被往返时间锁死「C 发一条等 S 应答收到应答再发下一条」——这条规则看起来稳妥每条消息都在上一条被确认之后才出发代价是速度每发一条都要完整等一个网络往返网络越远等待越长大量时间花在「等」而不是「传」上效率太慢这条路线注定要被换掉4.2 通用的流程并发地发送与应答1. 两种方案放在一起对照串行停等发一条停一条每条都等确认落地再发下一条稳当直观但速度被一个又一个往返时间锁死并发流水C 不必等 S 应答之后再发送而是并发地发送与应答——应答在回来的路上新消息已经在去路上两条线互不等待这是更通用的流程2. 快是有代价的新问题跟着并发进来并发换来了吞吐量也把「丢包」从一个小麻烦升级成了必须正面回答的问题发送端从此要面对一个串行时代不存在的疑问4.3 新问题丢的是哪一个1. 应答比报文少一个缺口对应不上C 在并发发送过程中如果丢了 1 个报文他收到的应答数量肯定比发出的报文少一个但「少一个」只能说明有丢说明不了丢的是哪个——发出去的报文对 C 来说长得都一样没有任何标记能把它们区分开不知道丢的是哪个就没法定向补救要定位得先让每个报文有自己的编号并发把「有没有丢」变成了容易回答的问题把「丢的是哪个」变成了新问题——这个新问题只能靠编号来解决。五、32 位序号与 32 位确认序号5.1 请求带序号应答带确认序号1. 两个 32 位字段配对出现TCP 报头里用 32 位序号和 32 位确认序号来确保可靠性发送方发消息时在自己报头里填上序号接收方应答时在自己报头里填上确认序号通俗口径下确认序号就是收到的序号加一——S 收到 C 序号为 x 的报文应答时把确认序号填成 x1序号和确认序号的关系落在报头上收发双方之间就是靠报头的这两个字段一来一回地交互机制没有任何额外通道2. 真实 TCP 的序号按字节编号上面按「报文个数」编号是为了立直觉的简化模型真实 TCP 的序号计的是字节位置字节流逐字节编号报文里填的是首字节的编号确认序号是期望收到的下一个字节的序号——这和 《计算机网络篇8》里「TCP 把数据当成一串无边界字节」是同一件事的另一面编号口径变了机制没有变序号标位置、确认序号标「期望的下一个位置」下面仍按简化模型讨论5.2 确认序号的语义之前的全部收到即累积确认1. 确认序号代表它之前的所有信息全部收到确认序号的语义是「代表指定序号之前的所有信息已经全部收到」——它确认的不是某一条报文而是一个截止位置到这个序号为止前面一串全部落袋这种「一个确认覆盖一串」的机制标准名字叫累积确认Cumulative Acknowledgment接收方不需要对每条报文单独回一个确认只要把「我已经连续收到了哪里」报出去发送方就能推算出前面全部的接收情况2. 累积确认的容错允许少量丢包「之前全部收到」这种写法带来实实在在的容错好处可以总结成一句话允许少量丢包某一条应答报文丢了不影响结论——后面更大的确认序号一到它覆盖的范围自然把丢掉那条应答要说的话补了回来应答报文本身允许丢确认的粒度是「位置」而不是「条数」一个确认顶一串不必逐条应答确认的开销也省了下来应答可以丢、确认可以省靠的都是「确认序号自带截止位置」这一个语义3. 乱序问题也由序号接管既然是并发发送报文到达就有先后之分——先发的不一定先到后发的可能抢先落地接收方拿到报文后可以根据序号重新排序把先到的后发的放回它该在的位置乱序问题就此解决——这是序号在「定位丢包」之外的另一个好处同一个 32 位序号同时干了三件事定位丢包、排序乱序、承载确认可靠性的地基就是它垫的序号给每个位置一个标记确认序号报出「连续收到了哪里」累积确认的容错和乱序的排序全部建立在这两个位置标记上。六、全双工通信要求两个独立的序号6.1 一个序号为什么不够用1. 单向通信的错觉确认序号既然就是序号加一看起来完全可以互相推算一个序号字段似乎就够用了这个判断成立的前提是前面讨论默认的视角单向通信——C 只发、S 只答一条道走到底一旦换成双向同时通信这个前提就塌了6.2 全双工双方既发信息又作应答1. TCP 是全双工通信TCP 里是全双工Full Duplex通信双方可以互相通信不仅有应答还有信息——C 和 S 随时可能各自作为发送方往外发数据每个方向上都有自己的「发送」要编号、自己的「接收」要确认两个方向各自独立计数谁也不能替谁记账2. 应答搭上反向数据的便车捎带应答全双工带来的一个直接机制是捎带应答Piggybacking反向要发数据时应答不必单独占一条报文直接填在自己数据报文的确认序号里捎过去应答被捎在信息里一起走「不仅有应答还有信息」说的就是这种一报两用的形态3. 双向流程把两个字段各归其位C 给 S 发信息C 在报头里填序号S 向 C 作确认S 在报头里填确认序号S 给 C 发信息S 在报头里填序号——此刻 S 是发送方用的是自己方向上的序号C 向 S 作确认C 在报头里填确认序号每个方向都完整地需要「序号 确认序号」这对字段方向之间互不共用——两个 32 位字段不是同一个数的两种写法而是两条方向各自的账本。序号和确认序号不是「一个数和它的加一」是两个方向各自的账本全双工一开两个独立字段就从可有可无变成了必须。七、全篇总结1. 4 位首部长度切出可变报头TCP 报头是 20 字节固定加选项以 4 字节为单位字段取值 [5, 15]报头范围 [20, 60]按首部长度读满为止其后全是有效载荷2. TCP 没有长度字段字节流没有边界UDP 靠 16 位长度字段保住报文边界TCP 报头里没有对应字段面向字节流OS 不能真实区分每一次传输的长度3. 确认应答只做一层不对应答作应答C 发消息、S 作应答但应答本身免检应答到达时它确认的事实已经成立确认链在一层处截断4. 可靠性的边界在最新报文有应答锁定的是历史消息最新报文永远没有应答可靠性悬空5. 并发发送引出「丢哪个」的问题串行等应答效率太慢通用的流程是并发地发送与应答应答比报文少一个只说明有丢定位丢的是哪个要靠序号6. 序号与确认序号垫起可靠性确认序号代表之前全部收到即累积确认允许少量丢包乱序按序号排序全双工下两个方向独立计数必须有独立的两个 32 位字段八、文末面试题8.1 推导题按本篇知识点附答案【推导】TCP 报头最少 20 字节一个 4 位的字段怎么把它标出来实际取值范围怎么算答关键在基本单位——协议规定首部长度以 4 字节为单位计算4 位二进制最大是 15对应 15×4 60 字节的上限固定 20 字节折合 5 个单位是下限所以字段实际取值 [5, 15]报头实际长度 [20, 60]选项部分最大 40 字节4 个比特靠放大单位盖住了 20 字节起步的可变报头。【推导】S 给 C 的应答没有任何人确认这条「免检」为什么不算漏洞答因为应答到达的那一刻它要确认的事实已经成立——C 收到应答说明 C 之前发的消息 S 已经收到如果再给应答配应答确认链会一层层无限叠加且每一层都不增加任何新的可靠性所以 TCP 裁掉循环、只确认一层可靠性一分没少。【推导】既然确认序号等于序号加一为什么序号和确认序号要做成两个独立的 32 位字段答因为 TCP 是全双工——两个方向都各自要发信息和作确认每个方向都有自己的序号要填、自己的确认要回加上应答可以捎在反向数据的报文里一起发一条报文要同时装下「我的序号」和「对你的确认」一个字段装不下两本独立的账。8.2 真题来源已核实转述注明TCP 的序列号有什么作用答标识发送出去的每一个数据的位置接收方据此把乱序到达的报文按序拼回、把重复到达的报文丢弃同时确认报文里的确认序号也建立在它之上让发送方知道哪些数据已经被正常接收——序号是 TCP 解决乱序、重复和确认这三件事的共同基础。【真题·转述自 小林coding《图解网络TCP 基本认识》】TCP 的确认应答号是什么意思解决什么问题答指下一次期望收到的数据的序列号发送端收到这个确认以后可以认为在这个序号之前的数据都已经被正常接收它解决的是丢包问题——发送方对比「发了什么」和「被确认到了哪里」就能定位出缺失的部分。【真题·转述自 小林coding《图解网络TCP 基本认识》】为什么 UDP 头部有「包长度」字段而 TCP 头部没有答TCP 的数据长度可以用 IP 总长度减去 IP 首部长度再减去 TCP 首部长度推出来报头里不需要重复记录UDP 保留这个字段一方面补齐首部到 4 字节的整数倍另一方面配合 8 字节定长首部直接给出整条数据报的边界。【真题·转述自 小林coding《图解网络TCP 基本认识》】什么是累积确认答TCP 的确认只确认到第一个丢失位置为止——接收方回的确认号表示「期望收到的下一个序号」等于一次性承认了它之前的所有数据都已收到比如收到包 1、2、3 之后回一个确认号 4发送方就知道前三个全部到位必要时只处理包 4一个确认覆盖一串报文而不必逐包确认。【真题·转述自 牛客网《常见 C 面试题及基本知识点总结二》】TCP 是如何保证可靠传输的答核心是序列号加确认应答——每个数据都有编号接收方按序号排序乱序、丢弃重复并通过确认号告诉发送方已经连续收到哪里没被确认的数据由重传机制补发再配合流量控制和拥塞控制调节发送节奏多套机制叠加在不可靠的 IP 之上拼出可靠传输。【真题·转述自 牛客网《面试官TCP 是如何保证可靠传输的》】为什么客户端和服务端的初始序列号 ISN 是随机生成且互不相同的答因为网络中的报文会延迟、会丢失、也可能被复制重发如果不同连接的初始序列号固定且相同旧连接迟到、重复的报文就可能落进新连接的序号范围里被当成合法数据随机且不同的 ISN 把不同连接的序号空间错开减小旧报文干扰新连接的概率。【真题·转述自 小林coding《图解网络TCP 连接建立》】TCP 的可靠不是承诺出来的是算出来的序号给每个位置一个标记确认序号报出一条截止线应答免检把确认链截在一层。可靠性从「尽力而为」变成「有账可查」靠的就是报头里这几笔账。
企业数字化 ERP 产品动态
相关推荐
如何释放10%~50%系统内存:Mem Reduct 内存清理与监控完整指南 如何释放10%~50%系统内存:Mem Reduct 内存清理与监控完整指南 【免费下载链接】memreduct Lightweight real-time memory management application to monitor and clean system memory on your computer. 项目地址: https://gitcode.com/gh_mirrors/me/memreduct … · 2026/11/5 6:44:31
ChatHub 八折优惠怎么领?All-in-One AI 聊天客户端的完整折扣指南 ChatHub 八折优惠怎么领?All-in-One AI 聊天客户端的完整折扣指南 【免费下载链接】chathub All-in-one chatbot client 项目地址: https://gitcode.com/gh_mirrors/ch/chathub
如果你也试过同时用 ChatGPT、Claude 和 Gemini 核对同一个答案,大概… · 2026/11/5 6:44:31
ADS122U04与STM32F410RB工业温度采集方案:UART接口ADC实战详解 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 7:35:44
ADS122U04IPWR + PIC18F66K40:PT100/NTC高精度温度采集方案解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 7:35:44
Figma设计稿转LVGL嵌入式UI:自动化链路与工程实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 7:35:44
ADS122U04IPWR+PIC18F56K42实现0.1℃工业温度测量 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 7:35:44
工业温度测量信号链设计:ADS122U04与PIC18F57Q43实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 7:35:44
1km人口分布栅格数据处理:口径、裁剪与时间序列分析 去年帮一位做城市扩张研究的朋友处理人口栅格,他拿到一份 2000—2023 年的 1km 精度人口分布栅格数据,第一件事就是把研究区内的像元值全部加总,想直接得到总人口曲线。结果算出来的数比公开统计口径少了将近三成,他一度以为是数据… · 2026/11/5 7:34:44
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38