Linux网络编程实战:从HTTP到自定义TCP协议的计算器重写
最近我把一个经典的“网络版计算器”小项目从HTTP JSON接口重写成了纯Linux下的自定义TCP协议版本。这个项目几乎每个学C语言网络编程的人都会遇到但大多数实现都是直接拼一个HTTP请求、用JSON做序列化真正卡住人的地方反而不是计算逻辑而是“一次请求怎么才能在两个独立进程之间安全地传过去再原样传回来”。这次我干脆放弃了HTTP在TCP之上手写了一套二进制协议从帧格式设计、粘包处理、字节序转换到抓包验证和多客户端并发压测全部跑通。整个过程非常值得记录既能把socket编程里那些“书上不讲但实战必踩”的坑都过一遍也能真正理解为什么很多内部服务不用HTTP而是选择自己定协议。这篇文章会按顺序拆解协议设计、服务端和客户端实现、调试验证链路以及几个我在实测中遇到并修复的问题。适合刚学完socket想动手做完整项目的读者也适合想理解自定义协议设计思路的人参考。1. 为什么这个项目不直接上HTTP而是自研协议先说说背景。网络版计算器的功能非常简单客户端发一个计算表达式服务端把结果算出来返回。拿HTTP来做无非就是POST一个JSON体到服务器服务器用JSON解析出操作数和运算符再返回JSON结果。听起来没什么问题但真在Linux上做一遍麻烦很快就暴露了。本地调试时curl一发就能看到结果感觉一切正常可一旦要放到内网多个服务之间互相调用HTTP的重量就开始拖后腿。一个最简单的{op:add,a:1,b:2}请求加上Content-Length、Host、Content-Type这些头随便就是两三百字节而真正有用的业务数据只有几十字节。解析侧还要处理HTTP头部跨多个TCP段、Content-Length与 body 对应关系、连接复用等等问题。为了一个“两数相加”的接口引入整套HTTP语义属于典型的“杀鸡用了牛刀”。更关键的一点是网络编程的基础能力恰恰被HTTP框架掩盖了。如果你只是调用某个现成的HTTP库那TCP流是字节流、消息边界由自己划分、粘包半包要靠缓冲区处理、字节序要做统一约定——这些底层概念你永远接触不到。而自定义协议天然逼着你面对这些问题。所以我把方案定为直接在TCP之上定义一套简单、固定、可扩展的二进制协议。选择二进制而不是文本是因为计算器场景的业务字段非常规整一个运算符、两个操作数、一个结果这类结构化数据用二进制表示最省空间解析时不用做字符串切割也更容易判断消息边界。如果需要兼容人工调试可以在协议外部单独写一个十六进制转储工具不必牺牲线上协议的紧凑度。协议设计时我给自己定了三条原则头部固定长度所有整数统一使用网络字节序大端负载部分采用可读的文本格式便于实验阶段排查问题响应必须携带请求的序列号支持后续多连接并发场景。第一版协议不需要完美但底子必须干净后续加字段、加功能不至于推翻重来。2. 协议格式从0开始设计字节序、魔数与错误码自定义协议的第一步是把“一条消息长什么样”定义清楚。我不打算用JSON或者XML做负载格式因为那样就失去了练习的意义。我们直接在TCP负载里画出一个帧结构规定好每个字段占多少字节、按什么顺序排列。2.1 头部结构14字节固定长度我定义的帧格式如下0 4 5 6 10 14 ---------------------------------- | magic| ver | type | seq | len | ---------------------------------- | payload (len bytes) |各字段含义magic4字节魔数固定为0xC1A1C0DE用来快速校验“这确实是我们协议的数据包”避免把无关数据当业务帧解析ver1字节版本号当前是0x01后续协议演进时可以据此做兼容判断type1字节消息类型0x01表示请求0x02表示响应0x03预留为心跳seq4字节无符号序列号客户端每次请求自增服务端在响应里原样抄回len4字节无符号整数表示后续payload的字节长度。头部一共 4 1 1 4 4 14 字节。payload长度由len字段指定理论上可以达到4GB范围但我在实现里强制限制最大不超过1024字节超过直接返回错误这能挡住很多畸形包和恶意超长包。2.2 负载格式请求与响应的文本约定头部解决“消息边界”问题payload则负责承载业务数据。我采用的payload格式非常简单请求: OP A B 响应: OK result 或 ERR error_message其中OP是运算符字符串支持ADD、SUB、MUL、DIV四种。A和B是浮点数用strtod解析。比如一次完整请求的payload是ADD 3.5 2.1对应的响应payload是OK 5.6如果出错了响应是ERR DIV_BY_ZERO为什么不直接用二进制float因为浮点数在不同语言、不同体系结构间的二进制表示并不完全一致而且文本形式在调试阶段可以直接用tcpdump看到内容降低排查难度。这个选择也说明一个道理协议设计不是越二进制越好而是要在开发成本、调试成本和传输效率之间取一个平衡点。2.3 为什么seq字段如此重要很多第一次写自定义协议的人会忽略seq。但如果你真正跑过多个并发请求就会立刻发现它的必要性TCP是全双工字节流客户端连续发送多个计算请求后服务端返回的多个响应在字节流里是排队到达的客户端根本没法只靠“先读先得”知道哪条响应对应哪条请求。有了seq每次请求编号响应原样带回编号客户端就能做精确配对。这个字段也顺便解决了未来扩展批量请求、异步回调、请求超时重传等问题属于花4字节买一个长期可扩展性。2.4 错误码设计宁可多不可少我的第一版协议里只设计了OK其余错误一律返回ERR。结果联调时发现服务端返回ERR后客户端只知道自己失败了不知道为什么失败排查效率极低。后来我把错误码细分成了以下几类错误码串含义ERR_BAD_REQpayload格式无法解析ERR_UNSUPPORTED运算符不在支持列表内ERR_DIV_ZERO除数为0ERR_TOO_LONG请求payload超过上限这样客户端拿到错误码后可以直接映射成用户可读的提示不需要再抓包猜答案。协议整体定稿后编码部分反而是最简单的了核心在于用htonl/htons统一字节序。x86这类小端机器上的数值如果不转换直接塞进TCP流对方用大端解析时读出来的魔数就变成了0xDEC0A1C1校验直接失败。所以服务端解析头部时所有uint32_t字段都调用ntohl恢复成主机序发送时调用htonl转成网络序。3. 服务端实现IO模型、帧解析与安全计算服务端是整个项目的重头戏。它要做三件事接受客户端的TCP连接、从字节流中还原出一个个完整帧、执行计算并回包。下面逐个拆解。3.1 IO模型选择epoll 单线程事件循环我对性能没有极端的追求但希望服务器能同时支撑几十个连接不卡顿所以放弃了最早的“每连接一个线程”模型。那个模型在小规模demo里很直观但线程数一多上下文切换和内存开销都很可观。最终采用的是Linux下非常经典的epoll 单线程事件循环模型epoll监听监听socket的可读事件有新连接到来时accept每个已连接的socket也注册进epoll同时维护一个读缓冲区可读事件触发后从socket里读数据追加到缓冲区然后尝试从缓冲区解析出完整帧解析出完整请求后调用计算函数把结果拼成响应帧写回客户端。这个模型的好处是单线程不存在并发加锁问题所有状态都集中在事件循环里调试简单。如果后续计算逻辑变重可以把计算任务丢给线程池但当前计算器场景毫秒级就能完成事件循环顺序处理没有任何压力。3.2 帧解析处理粘包与半包帧解析是最容易写错的部分也是新手最容易踩坑的地方。TCP是字节流recv()一次返回多少数据完全不确定可能一次只到了半个头部也可能一次到了三个半完整帧。因此服务端绝不能假设“一次recv就是一个完整请求”。我的做法是维护一个动态增长的缓冲区。每次收到新数据先追加到缓冲区末尾然后进入一个“尝试解析”循环while (buf_len HEADER_SIZE) { header parse_header(buf); if (buf_len HEADER_SIZE header.len) { // 头部完整但payload还没到齐需要继续等下一批数据 break; } payload buf HEADER_SIZE; handle_frame(header, payload); drop_frame_from_buffer(buf, HEADER_SIZE header.len); }这段逻辑看着简单但极容易忽略的细节是解析完成后必须把已消费的字节从缓冲区头部移除否则缓冲区会越积越大下一帧永远没法正确对齐。我见过好几个项目都是栽在这里一遇到粘包就出现“第一帧解析对了第二帧开头全是乱码”的诡异现象。另一个细节是缓冲区扩容。一个小技巧是预分配一个 64KB 的初始缓冲正常情况根本不会触发realloc还能顺手防住短时突发流量。3.3 计算核心不信任任何网络输入计算函数看起来只需要ADD 3.5 2.1这种字符串实际上最容易出现安全问题。如果直接调用系统函数或者用sscanf宽松解析遇到ADD abc def这种输入时行为完全不可控。我在解析payload时坚持“逐token校验”的策略按空格切分payload最多只接受3个token第一个token必须匹配ADD/SUB/MUL/DIV后两个token必须能被strtod完整转换且转换后endptr指向字符串结尾不允许出现3.5abc这类残留字符计算除法前先检查除数的绝对值是否小于某个极小阈值而不是直接判断等于0因为浮点数0的表示有正负之分。double a strtod(tokens[1], end); if (*end ! \0) return ERR_BAD_REQ;这套校验下来哪怕客户端发了恶意的畸形包服务端也只是返回一个错误码不会崩溃不会计算出莫名其妙的数值。3.4 响应发送避免短写与信号干扰计算完成后要回复响应帧。很多初学者会写一个send(fd, resp, len, 0)就以为发送完毕其实send在非阻塞模式下返回值可能小于len必须把剩余部分继续发送完。虽然单线程epoll下逻辑相对简单但数据量大或客户端接收缓慢时依然会出现部分写入。我的处理是用一个发送队列先把响应帧push到每个连接的发送缓冲区然后在事件循环里只对“可写”的连接调用drain_send()直到该连接的发送缓冲清空。这样既能保证数据完整发送也避免在单个连接上因为send阻塞而拖垮整个事件循环。还有一点必须强调捕获SIGPIPE。当客户端已经断开但服务端还在write时进程会收到SIGPIPE信号默认行为是直接终止进程。一个毫不起眼的小错误就能让整个服务静默退出排查起来极其崩溃。解决方案是在启动时加一行signal(SIGPIPE, SIG_IGN);忽略这个信号后send会返回EPIPE错误我们就可以通过错误码正常关闭连接。4. 客户端与调试链路从Python发帧到抓包验证服务端写完并不代表协议正确还需要一个能主动构造任意帧的“调包侠”客户端。C语言客户端当然要写但调试阶段我更推荐用Python快速验证协议格式因为它的struct模块处理二进制头部非常直观。4.1 用Python手工构造请求帧import socket, struct MAGIC 0xC1A1C0DE VERSION 0x01 TYPE_REQ 0x01 def make_frame(seq, text): payload text.encode(utf-8) header struct.pack(IBBII, MAGIC, VERSION, TYPE_REQ, seq, len(payload)) return header payload s socket.create_connection((127.0.0.1, 9527)) s.sendall(make_frame(1, ADD 3.5 2.1)) resp b while len(resp) 14: resp s.recv(4096) magic, ver, typ, seq, length struct.unpack(IBBII, resp[:14]) body b while len(body) length: body s.recv(4096) print(seq, body.decode())这段代码直接验证了头部可以正确被服务端解析、响应帧能完整收回来。struct.pack中的IBBII格式值得解释一下表示大端序I是无符号4字节B是无符号1字节所以IBBII正好对应magic/ver/type/seq/len14字节。如果这个Python脚本能拿到1 OK 5.6这样的输出说明从客户端编码、TCP传输、服务端解帧到响应编码这条主链路已经通了。4.2 C语言版客户端超时设置与连接复用验证完协议格式后我又写了一个精简C客户端目标有两个一是支持命令行直接执行./calc_client 127.0.0.1 9527 ADD 1 2二是能连续发送多个请求验证seq配对。这里有个容易踩的坑是recv超时。如果服务端一直不响应客户端可能永远阻塞在recv调用上。我给socket设置了接收超时struct timeval tv { .tv_sec 3, .tv_usec 0 }; setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, tv, sizeof(tv));超时后recv返回-1errno是EAGAIN/EWOULDBLOCK客户端可以打印超时信息并重试或退出而不会永远挂住。这个处理在实际联调中帮了我大忙因为偶尔服务端逻辑有bug时客户端能立刻暴露问题而不是卡死。4.3 抓包验证用tcpdump看字节流写协议的人如果不看抓包相当于闭着眼睛开车。我在本地用tcpdump直接抓取服务端端口的流量tcpdump -i lo port 9527 -XX -s 0-XX会以十六进制和ASCII双格式打印每个包的内容。一次正常的请求包会看到类似这样的输出c1 a1 c0 de 01 01 00 00 00 01 00 00 00 09 41 44 44 20 33 2e 35 20 32 2e 31对照头部字段c1 a1 c0 de是魔数01是版本01是请求类型00 00 00 01是seq100 00 00 09是payload长度9后面的ASCII文本正是ADD 3.5 2.1。看到这一串协议的每一个设计都能在真实网络包上找到对应关系那种“纸上协议真的落地了”的感觉非常踏实。5. 排错实录四个让我绕路的坑及其根因这部分不是凑字数而是我自己在做这个项目时真实遇到、并且花了较长时间才定位的问题。每一个都很有代表性。5.1 第一坑魔数校验失败客户端服务端各说各话问题现象Python客户端发出的帧服务端日志提示“magic mismatch”但抓包显示数据明明是对的。排查好久才发现我的C程序从缓冲区解析头部时没有把ntohl之后的值重新赋值回去直接拿网络序的魔数去比较if (*(uint32_t *)buf ! MAGIC) { ... } // 错误写法由于同一台机器上客户端和服务端都是小端htonl转换后的值在小端机器上解回读出来还是原来那个魔数所以本机调试完全正常。但如果换成另一台大端机器这个比较就会失败。随后我把所有头部字段的解析都改成uint32_t magic ntohl(*(uint32_t *)buf);这样无论运行在哪台机器上读到的主机序值都是0xC1A1C0DE。这个坑让我彻底记住了凡是跨机器传输的整数字段必须显式做字节序转换。5.2 第二坑send没有发完响应帧被截断服务端回复大payload时客户端偶尔收到不完整的响应。一开始我怀疑是网络问题后来加日志才发现send返回了部分长度。Linux的send在非阻塞模式下可能只发送了缓冲区的部分数据剩余数据需要继续发送。如果直接把send的返回值忽略掉就会出现偶尔性截断——在小数据量时几乎不会触发一旦payload变大或者网络出现拥塞就显现出来。修复方式就是前面提到的发送队列维护一个每连接独立的待发送缓冲区send返回多少就移除多少剩余的下次epoll触发可写事件时继续发。这也让我认识到网络编程里“一次调用成功”不等于“一次调用发完”这是跟本地文件读写差异最大的地方。5.3 第三坑SIGPIPE导致服务端静默退出服务运行了十分钟左右突然没有任何日志就消失了。第一反应是程序崩溃但加了-g编译后用调试工具也没看出core dump。后来才发现是SIGPIPE。当客户端主动断开TCP连接而服务端仍在往这个socket写数据时内核会向进程发送SIGPIPE信号默认动作是终止进程。对于长驻服务来说这是绝对不能接受的默认行为。解决方案很干脆signal(SIGPIPE, SIG_IGN);忽略这个信号后写入已关闭的socket只是返回EPIPE错误服务端可以正常通过错误码清理该连接。这也是每个写网络服务程序的人必须记住的一条经验。5.4 第四坑seq错乱并发响应配对不上给客户端加上并发能力之后我发起了10个同时进行的请求结果收到的响应seq顺序跟发送顺序完全不一致。起初以为服务端搞乱了实际上服务端根本没有乱TCP只是保证字节流顺序并不保证多个连接的响应返回顺序和请求顺序一致。当10个请求从同一个连接连续发出后服务端一次epoll事件里可能读到了3个请求它按顺序处理并回复了3个响应但第4个请求的响应可能因为多线程线程池的调度顺序先出现了。解决方法是利用seq字段。客户端不再“先读到的响应就是当前请求的响应”而是维护一个seq到回调函数的映射表读到一个响应帧后查表找到对应的待处理请求然后继续读下一条。这样一来响应顺序再怎么乱客户端也能精确归位。这个坑让我更深刻地理解了协议里设计seq字段的含金量它不只是为了追踪日志而是在并发场景下维护请求与响应映射关系的基石。6. 压测数据与后续演进方向项目跑通之后我又做了一轮本地压测目的是确认这套自定义协议的性能和稳定性不是“看起来能跑”而已。6.1 简单压测结果对比我在同一台Linux机器上做了两组对比测试一组走自定义二进制协议一组走HTTPJSON接口。测试方式是Python脚本开启多个线程每个线程发送固定数量的计算请求统计总耗时和成功率。指标自定义二进制协议HTTPJSON单请求平均耗时约0.04ms约0.5ms每个请求传输字节数41字节280字节10并发1000请求成功率100%100%需要处理的边界问题粘包/半包Content-Length/连接复用这个对比不能说HTTP完全不行因为本机回环的网络延迟极低主要差距来自协议头开销和JSON解析成本。但如果把这套计算服务部署到内网成千上万次调用的场景里自定义协议节省的带宽和解析时间会非常可观。不过我也要泼一盆冷水压测数据好不代表可以随便自研协议。对于大多数业务系统直接使用成熟RPC框架是更稳妥的选择因为框架解决了鉴权、序列化、超时重试、负载均衡等一系列问题。自定义协议更适合作为学习项目或者在通信双方高度可控、消息格式非常稳定的内部场景下使用。6.2 可能的扩展方向这个项目做完之后我整理出了几个后续可以继续折腾的方向给协议加一个简单的鉴权字段比如握手阶段交换token之后每个请求都携带token摘要用base64编码payload让协议包可以通过文本管道传输方便日志检索支持批量计算请求一个帧里携带多个表达式进一步降低头部开销占比参考主流RPC框架的做法引入可选的压缩算法对payload超过一定阈值的帧启用压缩把计算函数从同步执行改成线程池异步执行提升高并发下的吞吐能力。这些扩展点每一个都有独立的原理值得深入也都是自定义协议项目后续很自然的演进方向。6.3 一点个人体会如果你也想找一个能一次覆盖Linux网络编程核心知识点的练习项目网络版计算器定制的自定义协议非常合适。它门槛不高——会基本的socket API就能动手——但要把协议设计、字节序、粘包处理、并发配对这些问题全部想明白又需要非常扎实的底层理解。我在做完这个项目之后再看那些开源网络库的源码明显比之前顺畅得多因为很多我以前“看不懂为什么这么写”的代码现在都能对应上一个具体的踩坑场景。从最简单的ADD 1 2跑通到支持多连接并发、抓包验证、压测优化你会发现网络编程不是玄学而是一环扣一环的工程问题。每一步遇到的坑都有它的根因和对应的解法。把这套链路完整走一遍比看十遍理论书都管用。

相关新闻

SpringBoot+Vue+MySQL文物征集管理系统设计与实现全解析

SpringBoot+Vue+MySQL文物征集管理系统设计与实现全解析

做毕设或者课程设计,选管理系统项目是一个非常稳妥的方向,而“SpringBoot Vue MVC Java MySQL”这套组合,基本算是全栈入门项目的黄金搭配。但大多数同学在网上找到的源码要么过于简陋,要么结构混乱只能跑通却讲不清原理。这篇…

2026/10/10 16:48:16 阅读更多 →
被误读的AGI声明:黄仁勋的真实立场与AI工程化评测方法

被误读的AGI声明:黄仁勋的真实立场与AI工程化评测方法

如果你最近在技术圈刷到过这样一条消息——Nvidia CEO 说“我们已经实现了 AGI,但这并不重要”——先别急着转发,也别急着站队。因为这个标题大概率是二手转述的产物,语境已经被裁剪掉了。从目前可查的公开演讲和报道看,黄仁勋并没…

2026/10/10 16:47:14 阅读更多 →
Windows 11 v26h2深度测评:性能优化与升级实操指南

Windows 11 v26h2深度测评:性能优化与升级实操指南

1. 为什么一个系统版本更新值得单独写一篇长文我平时不太喜欢写系统测评,因为大多数版本更新无非就是改改界面、修修Bug,写出来像流水账。但这次不一样。Windows 11 v26h2这个版本,我从早期测试通道一路跟到正式推送,前后在四台不…

2026/10/10 16:47:14 阅读更多 →

最新新闻

免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线

免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线

免费开源 vs 截图 API 月入 2000 美金:独立开发的两条变现路线 【免费下载链接】tendedero Screenshots, hung out to dry. A tiny native macOS app that hangs every screenshot on a line at the top of your screen. 项目地址: https://gitcode.com/gh_mirror…

2026/10/10 20:54:37 阅读更多 →
基于Python的考研学习系统设计与实现——Django毕设完整项目解析

基于Python的考研学习系统设计与实现——Django毕设完整项目解析

每年到了毕业设计季,总有人私信问我:"有没有现成的毕设源码""为什么我照着网上的教程敲代码,跑起来全是报错"“答辩的时候老师让我讲核心代码,我该怎么讲”。这套基于Python的考研学习系统的设计与实现&#…

2026/10/10 20:54:37 阅读更多 →
品牌宣传素材网站哪个靠谱?商用正版素材平台推荐

品牌宣传素材网站哪个靠谱?商用正版素材平台推荐

在品牌宣传与内容创作日益高频的今天,选择素材平台已不仅仅是“找张好看的图”那么简单。对于自媒体创作者、电商运营、设计师及企业市场团队而言,版权合规是商业使用的安全底线。一张来源不明的图片、一段未获授权的背景音乐,都可能让精心策…

2026/10/10 20:54:37 阅读更多 →
从混乱到有序:2026大型集团数据治理的破局之道

从混乱到有序:2026大型集团数据治理的破局之道

引言:当数据成为负担而非资产过去五年,大量大型集团完成了数据中台的基础搭建,打通了ERP、CRM、MES等核心业务系统。然而,一个普遍困境随之浮现:平台建好了,数据接进来了,业务部门却依然感受不到…

2026/10/10 20:54:37 阅读更多 →
full attetnion和casual attention

full attetnion和casual attention

简单理解就是:Full Attention 能看全部 token;Causal Attention 只能看当前和过去,不能偷看未来。Full Attention(全注意力)假设序列是 ,那么每个位置都可以和所有位置做 attention:所以它是双向…

2026/10/10 20:54:37 阅读更多 →
TikTok Shop 跨境认证海外仓解读:欧洲本地托管怎么接

TikTok Shop 跨境认证海外仓解读:欧洲本地托管怎么接

2026 年开年,TikTok Shop 跨境电商本地托管正式上线欧洲,率先开放德国、法国、意大利、西班牙四个欧盟国家。对做内容电商的跨境卖家来说,这是一个新的增量战场:流量红利刚开启,本地托管模式让商家只需备货到欧洲本地仓…

2026/10/10 20:53:37 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

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/10 11:14:25 阅读更多 →
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/10 1:36:08 阅读更多 →
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/10 11:14: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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →