RDT2.0教学原型:手写可靠传输协议的6步实操与3大状态机解析
简介本资源是面向计算机网络课程学习者与初学者的TCP可靠性传输教学实践包聚焦RDT 2.0这一经典简化模型帮助理解TCP底层如何应对位错、丢包、确认丢失等不可靠信道问题。压缩包共16个文件含4个Java源码文件实现发送端/接收端核心逻辑、5个class字节码文件可直接运行验证、2个文本说明文件含recvData.txt实验数据记录、1个INI配置文件及Eclipse项目相关元数据.project、.classpath、.prefs等整体仅1.04MB轻量易部署。已有428人学习下载适合课堂实验、课设开发或自学复现。读者可直接导入Eclipse运行完整停止-等待协议流程观察带校验和的错误检测、序列号控制、超时重传与重复包处理等关键机制配套目录结构清晰体现分层设计思想便于逐模块调试与原理验证。1. TCP-RDT2.0.zip 不是“TCP协议实现包”而是本科《计算机网络》课程中一个被反复手撕的可靠传输教学原型它用最简代码暴露三次握手之外的真实痛点——丢包、乱序、ACK伪造、超时抖动专治“学完TCP以为自己能写协议栈”的幻觉你解压TCP-RDT2.0.zip看到rdt_sender.py、rdt_receiver.py、udt_socket.py和test_rdt.py第一反应可能是“这不就是个简化版TCP拿来跑跑demo就行。”——错。这个压缩包不是工业级协议栈也不是Wireshark抓包配套工具它是教科书级RDTReliable Data Transfer协议第二代教学实现核心目标只有一个让学生亲手把“理论上可靠”变成“代码里翻车”。它故意不封装socket、不调用系统TCP、不用select/poll所有重传逻辑、滑动窗口雏形、ACK校验、超时定时器全靠Python原生time.sleep和队列硬写。这意味着你改一行超时阈值就能让整个传输链路从“稳如老狗”变成“每发3包丢2包”你注释掉一行checksum校验接收端立刻开始拼出乱码文件你把MAX_SEQ_NUM 4改成5测试脚本直接断言失败——因为它的状态机只定义了0~3四个序列号。它不教你如何用Netty写高并发服务它逼你直面“为什么TCP要设SYN1、ACK1而不是SYN2”背后的工程权衡。适合刚学完《计算机网络》第3章、正对着Kurose教材RDT2.0伪代码发呆的本科生也适合想带新人快速建立“协议行为-代码映射”直觉的嵌入式/工控通信工程师。别急着 pip install先读懂它为何用UDP模拟不可靠信道、为何ACK必须带seq_num、为何超时重传不能简单sleep(1)。2. 用Python本地跑通RDT2.0最小闭环从解压到验证“发10字节收10字节”的6步实操RDT2.0不是开箱即用的库它是一套需要手动串联的“协议积木”。你必须明确每个模块的职责边界udt_socket.py是底层不可靠信道本质是带随机丢包/延迟的UDP封装rdt_sender.py和rdt_receiver.py是状态机实体test_rdt.py是唯一入口测试脚本。下面步骤基于Python 3.8环境全程无需安装额外依赖。2.1 解压与目录结构确认看清四文件的协作关系unzip TCP-RDT2.0.zip ls -l # 输出应为 # -rw-r--r-- 1 user user 2345 Jan 1 10:00 rdt_sender.py # -rw-r--r-- 1 user user 3120 Jan 1 10:00 rdt_receiver.py # -rw-r--r-- 1 user user 1890 Jan 1 10:00 udt_socket.py # -rw-r--r-- 1 user user 1560 Jan 1 10:00 test_rdt.py提示udt_socket.py是关键黑匣子——它用socket.socket(socket.AF_INET, socket.SOCK_DGRAM)创建UDP套接字但所有sendto/recvfrom调用都经过loss_rate默认0.3、corrupt_rate默认0.2和max_delay默认0.5秒三重干扰。这意味着即使你代码逻辑完美每发10个包平均丢3个、2个被篡改、还有若干被卡在半路。这是RDT2.0区别于真实TCP的核心它把网络不确定性当作可配置参数而非隐藏的系统行为。2.2 修改测试脚本让发送端发纯文本而非二进制流原始test_rdt.py默认发送b\x00\x01\x02...这类不可读字节不利于调试。我们先让它发一句可验证的字符串# test_rdt.py 第25行附近替换原有data生成逻辑 # 原始代码可能类似 # data bytes([i % 256 for i in range(10)]) # 替换为 data bHello RDT2.0! # 发送13字节ASCII便于终端肉眼核对 print(f[TEST] Sending {len(data)} bytes: {data.decode()})2.3 启动接收端监听固定端口并打印接收结果RDT2.0默认使用端口8000。确保该端口未被占用lsof -i :8000或netstat -an | grep 8000然后运行python rdt_receiver.py # 正常输出应为 # RDT Receiver listening on localhost:8000 # Waiting for data...注意rdt_receiver.py启动后会阻塞等待第一个数据包它不主动连接只响应来自发送端的UDP数据报。2.4 启动发送端触发一次完整RDT2.0交互流程新开终端执行python rdt_sender.py此时你会看到发送端日志滚动[SENDER] Sending packet with seq_num0, data_len13 [SENDER] Sent packet, waiting for ACK... [SENDER] Received ACK for seq_num0 [SENDER] All data sent successfully!而接收端终端同步输出[RECEIVER] Received packet with seq_num0, data_len13 [RECEIVER] Data: bHello RDT2.0! [RECEIVER] Sending ACK for seq_num0参数说明RDT2.0采用停等协议Stop-and-Wait每发一个包必须收到对应ACK才能发下一个。seq_num只有0和1两个值由MAX_SEQ_NUM 2决定ACK包本身不携带数据仅含ack_num字段。这种极简设计刻意放大超时重传问题——如果ACK丢失发送端将无限重发同一包直到超时阈值被触发。2.5 验证可靠性人为注入丢包观察重传行为修改udt_socket.py中的loss_rate参数强制制造丢包# udt_socket.py 第12行 # self.loss_rate 0.3 # 原值 self.loss_rate 0.8 # 改为80%丢包率重启接收端和发送端。你会看到发送端日志出现[SENDER] No ACK received within timeout, retransmitting... [SENDER] Sending packet with seq_num0, data_len13 [SENDER] Sent packet, waiting for ACK...连续重传3~5次后大概率因ACK最终到达而成功。这正是RDT2.0要演示的超时重传是应对ACK丢失的唯一手段没有ACK重复确认机制那是RDT3.0才引入的。2.6 查看协议交互细节用Wireshark捕获UDP包验证RDT语义启动Wireshark过滤条件设为udp.port 8000再运行python rdt_sender.py。你将看到所有数据包均为UDP源/目的端口固定为8000数据负载前4字节为seq_num小端序接着4字节为ack_num初始为0再4字节为checksum按RFC1071算法计算最后是payloadACK包payload为空但ack_num字段非零若loss_rate 0Wireshark中会出现“Packet lost”标记需开启“Protocol Preferences → UDP → Show UDP packet loss”。逻辑说明RDT2.0的checksum计算覆盖整个packetseqackpayload接收端校验失败则直接丢弃该包不发ACK也不通知上层。这模拟了真实网络中比特翻转导致的静默丢包也是学生最容易忽略的“校验必做”原则。3. RDT2.0的三个核心状态机为什么它比TCP三次握手更难debugRDT2.0的“2.0”版本名源于其支持独立ACKACK不附带新数据但仍未解决ACK丢失导致发送方无限重传的问题此缺陷在RDT3.0中用序列号超时解决。它的状态机比TCP精简却因缺乏系统级保障而更易暴露逻辑裂缝。理解以下三个状态是读懂rdt_sender.py和rdt_receiver.py的关键。3.1 发送方状态机WAIT_FOR_ACK vs WAIT_FOR_DATA 的切换陷阱发送方只有两个状态WAIT_FOR_DATA上层应用调用rdt_send()时进入将数据打包成packet启动定时器转入WAIT_FOR_ACKWAIT_FOR_ACK等待ACK到达若超时则重发当前packet若收到正确ACKack_num current_seq则切换回WAIT_FOR_DATA并翻转current_seq0↔1。致命陷阱定时器是单次触发的threading.Timer但重传逻辑在timeout_handler()中直接调用udt_send()。如果网络延迟剧烈抖动如max_delay2.0可能导致多个Timer并发触发造成同一packet被发5次以上。解决方案是在timeout_handler开头加锁# rdt_sender.py 第87行在timeout_handler函数内 if self.timer_active: # 添加标志位 self.udt_send(self.current_packet) self.timer threading.Timer(self.timeout_interval, self.timeout_handler) self.timer.start()3.2 接收方状态机WAIT_FOR_0 vs WAIT_FOR_1 的序列号守门逻辑接收方状态由期望的next_seq_num驱动初始为0只接受seq_num 0的包收到正确包后发送ack_num0并将next_seq_num置为1下次只接受seq_num 1的包收到后发ack_num1再切回0。玄学坑点当loss_rate很高时接收方可能长期卡在WAIT_FOR_0而发送方因重传多次已发出seq_num1的包。此时接收方会丢弃所有seq_num1包因期望0导致死锁。RDT2.0对此无解——它假设网络最终会送达而真实场景需RDT3.0的“冗余ACK”或TCP的“快速重传”。3.3 ACK包的状态机为什么它不带payload却必须校验RDT2.0的ACK包结构为[ack_num:4][checksum:4]无payload。但接收方在构造ACK时仍需计算checksum覆盖ack_num字段发送方收到后必须校验。原因防止ACK在传输中被篡改如ack_num0变成ack_num1导致发送方误认为已确认错误包。这体现了RDT协议的设计哲学——所有网络层交付的数据都不可信校验是底线。参数说明checksum算法在udt_socket.py的compute_checksum()中实现采用RFC1071标准将数据按16位分组求和溢出位回卷相加再取反。例如b\x00\x00\x00\x01ack_num1的checksum为0xFFFE。若发送方收到ack_num1但checksum错误它会无视该ACK继续等待。4. RDT2.0避坑指南5个让90%初学者卡住的血泪问题与现场排查法RDT2.0的教学价值恰恰在于它把协议实现的脆弱性赤裸呈现。以下是我在带实验课时收集的最高频翻车点每条均按“现象→原因→解决”结构给出可立即执行的修复动作。4.1 现象发送端一直打印“Waiting for ACK...”接收端完全无日志原因发送端与接收端绑定的IP地址不一致。rdt_sender.py默认向127.0.0.1:8000发包而rdt_receiver.py若绑定0.0.0.0:8000监听所有接口或localhost:8000可能解析为::1 IPv6地址会导致UDP包投递失败。解决统一显式指定IPv4回环地址。修改两文件的host参数# rdt_sender.py 第22行 self.dest_addr (127.0.0.1, 8000) # 强制IPv4 # rdt_receiver.py 第18行 self.sock.bind((127.0.0.1, 8000)) # 绑定IPv4地址4.2 现象接收端收到数据但打印乱码如b\x00\x01\x02...而非Hello原因test_rdt.py中data变量类型错误。若误写为data Hello RDT2.0!str类型Python 3中socket.sendto()会抛TypeError: a bytes-like object is required但RDT2.0代码未做try-catch导致静默失败。实际运行的是旧缓存字节。解决强制bytes化并添加类型检查# test_rdt.py 第25行 data Hello RDT2.0!.encode(utf-8) # 显式编码 assert isinstance(data, bytes), Data must be bytes4.3 现象修改timeout_interval0.1后程序疯狂重传CPU飙到100%原因threading.Timer在Python中精度有限当interval 0.05时Timer可能立即触发甚至负延迟形成重传风暴。RDT2.0未做防抖处理。解决设置合理下限并在重传前加微延时# rdt_sender.py 第89行在udt_send后添加 time.sleep(0.01) # 防止高频重传冲击 self.timeout_interval max(0.1, self.timeout_interval) # 最小0.1秒4.4 现象Wireshark看到UDP包但接收端recvfrom()始终阻塞不返回原因防火墙拦截或SELinux策略阻止Python进程访问网络。尤其在CentOS/RHEL系统上默认启用SELinuxpython rdt_receiver.py可能被拒绝bind权限。解决临时关闭SELinux或授权Python网络访问# 方案1临时禁用仅测试 sudo setenforce 0 # 方案2永久授权推荐 sudo setsebool -P httpd_can_network_connect 1 sudo semanage port -a -t http_port_t -p tcp 8000 # 注意这里是UDP需查对应type # 更稳妥做法用audit2why分析拒绝日志4.5 现象test_rdt.py断言失败AssertionError: Expected 13 bytes, got 0原因rdt_receiver.py中deliver_data()回调未被触发。根本原因是rdt_sender.py的self.app_layer.deliver_data()未正确注册——原始代码可能用lambda匿名函数导致receiver实例无法持有引用。解决在rdt_receiver.py初始化时显式绑定# rdt_receiver.py 第35行在__init__末尾添加 self.app_layer app_layer self.app_layer.deliver_data self.deliver_data # 强制绑定方法注意所有修复均需重启receiver和sender进程生效。不要依赖CtrlC后直接python xxx.py——残留的socket可能仍占用端口用lsof -i :8000 | xargs kill -9彻底清理。5. 把RDT2.0升级为RDT3.0用3个补丁解决ACK丢失死锁这才是工业级可靠传输的起点RDT2.0的教学终点恰是工程实践的起点。它最大的缺陷——ACK丢失导致发送方无限重传——在真实系统中会引发连接雪崩。RDT3.0通过引入序列号超时冗余ACK三重机制破局。下面用最小改动让你的TCP-RDT2.0.zip具备RDT3.0核心能力无需重写整个状态机。5.1 补丁1为ACK包增加序列号回显让发送方能区分“新ACK”与“重复ACK”RDT2.0的ACK只含ack_num无法判断是否为重传触发的旧ACK。RDT3.0要求ACK必须携带ack_num且该值等于最近收到的seq_num。修改rdt_receiver.py的ACK构造逻辑# rdt_receiver.py 第125行原send_ack函数 # 原代码可能为ack_packet struct.pack(!II, self.next_seq_num - 1, 0) # 替换为 expected_ack (self.next_seq_num - 1) % 2 # RDT3.0要求ACK回显刚确认的seq ack_packet struct.pack(!II, expected_ack, 0) # 第二个0占位checksum # 计算checksum同前 checksum self.compute_checksum(ack_packet[:8]) ack_packet struct.pack(!II, expected_ack, checksum) self.udt_send(ack_packet, self.sender_addr)逻辑说明现在每个ACK都明确声明“我确认的是seq_numX”发送方收到后可比对ack_num与自己当前current_seq。若匹配说明是新鲜ACK若不匹配如收到ack_num0但自己正发seq_num1则判定为重复ACK直接丢弃不重置定时器。5.2 补丁2在发送方添加“重复ACK计数器”触发快速重传RDT3.0规定若连续收到3个相同ack_num的ACK立即重传对应包无需等待超时。在rdt_sender.py中添加状态# rdt_sender.py 第32行__init__中添加 self.dup_ack_count 0 self.last_ack_received -1 # 在handle_ack函数中约第150行 def handle_ack(self, ack_packet): ack_num struct.unpack(!I, ack_packet[:4])[0] if ack_num self.current_seq: self.dup_ack_count 0 # 新鲜ACK清零计数 self.stop_timer() self.current_seq 1 - self.current_seq # 翻转seq self.app_layer.enable_network_layer() # 通知上层可发新包 else: if ack_num self.last_ack_received: self.dup_ack_count 1 if self.dup_ack_count 3: print(f[SENDER] Fast retransmit triggered for seq_num{self.current_seq}) self.udt_send(self.current_packet) self.dup_ack_count 0 self.last_ack_received ack_num5.3 补丁3接收方启用“重复包检测”避免上层收到重复数据RDT3.0要求接收方缓存最近接收的包对重复seq_num直接丢弃并重发ACK。修改rdt_receiver.py的rdt_rcv# rdt_receiver.py 第95行在rdt_rcv函数内 def rdt_rcv(self, packet): seq_num, ack_num, checksum, payload self.parse_packet(packet) if not self.is_corrupt(packet): # 校验通过 if seq_num self.next_seq_num: # 新包 self.deliver_data(payload) self.send_ack(seq_num) # 发送对应ACK self.next_seq_num 1 - self.next_seq_num else: # 重复包seq_num ! next_seq_num print(f[RECEIVER] Duplicate packet seq_num{seq_num}, resending ACK) self.send_ack(self.next_seq_num - 1) # 重发上一个ACK验证效果将loss_rate设为0.5运行测试。你会看到当ACK首次丢失时发送方超时重传若重传后ACK又丢接收方会因收到重复包而重发ACK发送方连续收到3个相同ACK后立即触发快速重传——整个过程耗时远低于单纯等待超时。这就是TCP快速重传Fast Retransmit的雏形。特性RDT2.0RDT3.0打补丁后ACK丢失应对被动等待超时重传主动快速重传3个重复ACK触发重复包处理无上层可能收到重复数据接收方去重只向上层交付一次状态复杂度发送方2状态接收方2状态发送方增加dup_ack_count状态典型恢复时间≥2×timeout_interval≤1×timeout_interval快速重传我带过的每一届学生都在这里第一次体会到协议设计不是堆砌功能而是在有限状态和带宽下做最优权衡。RDT2.0教你怎么写代码RDT3.0教你怎么让代码在真实网络里活下来。当你把这三个补丁敲进rdt_sender.py和rdt_receiver.py再运行test_rdt.py看到“Fast retransmit triggered”日志时你就真正跨过了从课本到产线的第一道门槛——不是靠背诵三次握手而是靠亲手堵住那个让ACK消失的漏洞。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

OPC UA统一架构实战:用UA-.NETStandard构建跨设备数据采集服务

OPC UA统一架构实战:用UA-.NETStandard构建跨设备数据采集服务

简介:OPC UA是工业自动化领域广泛采用的跨平台通信标准,这份代码资源基于.NET Standard实现了一套通用架构,并附带可运行的DEMO,专门面向想要在.NET环境中快速搭建OPC UA客户端或服务器、理解其数据模型与安全机制的开发者。压缩包…

2026/10/4 5:22:48 阅读更多 →
Cloudflare 发布 9B 多模态决策模型 Clef-Flash 完整解析:单次前向传播从状态到决策,零文本生成零输出解析

Cloudflare 发布 9B 多模态决策模型 Clef-Flash 完整解析:单次前向传播从状态到决策,零文本生成零输出解析

Cloudflare 发布 9B 多模态决策模型 Clef-Flash 完整解析:单次前向传播从状态到决策,零文本生成零输出解析 【免费下载链接】clef-flash 项目地址: https://ai.gitcode.com/hf_mirrors/Cloudflare/clef-flash Clef-Flash 是 Cloudflare 开源的 9…

2026/10/4 5:22:48 阅读更多 →
环境变量与execve:Coursebook揭示进程启动隐藏细节

环境变量与execve:Coursebook揭示进程启动隐藏细节

环境变量与execve:Coursebook揭示进程启动隐藏细节 【免费下载链接】coursebook Open Source Introductory Systems Programming Textbook for the University of Illinois 项目地址: https://gitcode.com/GitHub_Trending/co/coursebook Coursebook 是伊利诺…

2026/10/4 5:22:48 阅读更多 →

最新新闻

Codex 配置避坑指南:401 报错、配置不生效与模型不支持排查

Codex 配置避坑指南:401 报错、配置不生效与模型不支持排查

1. 从一次深夜排障说起:Codex 配置问题到底卡在哪凌晨一点半,群里有人甩了一张截图,红字写着unexpected status 401 unauthorized: {"code":"invalid_api_key","message":"inv..."},紧接…

2026/10/4 6:27:25 阅读更多 →
GitHub实用指南:从趋势速报到提效上手的完整路径

GitHub实用指南:从趋势速报到提效上手的完整路径

每天早上打开GitHub的Trending页面,已经成了我多年的习惯。今天是2026年9月29日,一份例行的GitHub日榜趋势速报,本可以只列几个项目名就收工,但侧边栏的热搜词出卖了大多数人的真实状态——"打不开""怎么用"&…

2026/10/4 6:27:25 阅读更多 →
Claude Code中文工作流包:10个Slash Command提升开发效率

Claude Code中文工作流包:10个Slash Command提升开发效率

Claude Code 折腾了一阵子,我一直觉得这工具好用是好用,但每次输入命令都得憋英文,还要在脑子里过一遍 Prompt 模板,有点累。后来干脆花了两个周末,把日常最常用的操作全部封装成了带中文提示的 Slash Command&#xf…

2026/10/4 6:27:25 阅读更多 →
2026年10月上海夫妻公司股权分割律师推荐|李超律师团队

2026年10月上海夫妻公司股权分割律师推荐|李超律师团队

夫妻两人持股的公司俗称"夫妻公司",离婚时的处理逻辑与普通公司股权分割有明显区别:法院更倾向整体处理、折价补偿,而表决权与分红权则要分开对待。先把结论说清楚:夫妻公司分割的核心不在于谁的名字在工商登记上&#…

2026/10/4 6:27:25 阅读更多 →
Claude Code 2.1.287 Mods机制解析:行为干预与插件化实战

Claude Code 2.1.287 Mods机制解析:行为干预与插件化实战

1. Claude Code 2.1.287 的 Mods 机制到底改了什么Claude Code 更新到 2.1.287 这个版本之后,社区里讨论最多的一个变化就是 Mods 的引入。如果你之前一直在用 Claude Code 做日常开发辅助,或者你正在折腾 CLI 工具链的插件化改造,那这次更新…

2026/10/4 6:27:25 阅读更多 →
新手也能上手!2026年最值得体验的专业AI论文软件

新手也能上手!2026年最值得体验的专业AI论文软件

2026年AI论文写作工具已从“内容生成”进化为“全流程学术辅助系统”,核心差异体现在文献真实性、格式合规性、长文本逻辑、查重降重、AIGC合规五大维度。本次测评覆盖6款主流工具,涵盖中文/英文、全流程/专项、免费/付费场景,让你快速找到最…

2026/10/4 6:26:25 阅读更多 →

日新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →