Linux网络编程实战:自定义协议实现网络计算器
最近把Linux下的网络编程重新捋了一遍顺手写了一个基于自定义协议的网络版本计算器。这个东西看起来简单但牵扯到的点一点不少自定义协议怎么设计、TCP粘包怎么处理、表达式怎么解析、多客户端怎么并发全都要落实。正好借这个项目把“Linux 自定义协议 网络”这套组合从设计到上线完整跑通了一遍。这篇文章就把我完整的实现思路、协议格式、关键代码和踩过的坑都放出来适合正在学Linux网络编程、想搞明白自定义协议到底怎么玩或者准备做类似练习项目的朋友参考。1. 项目解析网络计算器到底在做什么1.1 标题里的三个关键点先拆标题“Linux”、“自定义协议”、“网络版本计算器”。Linux是运行环境也是这个项目的主战场。几乎所有网络编程的基础操作都要在这里验证比如socket、bind、listen、accept、fork或pthread、epoll这些API。自定义协议是核心。不做HTTP不套现成的RPC就是从头定义一个二进制协议规定客户端和服务器之间怎么握手、怎么发请求、怎么回响应连包里每个字节的用途都是我们自己说了算。网络版本计算器是业务载体。客户端把表达式字符串发给服务器服务器计算完把结果返回。本质上就是一个“远程计算服务”只不过把计算能力放在服务器端。这个项目解决的实际问题很简单让客户端不直接调用计算逻辑而是通过网络把请求发给服务端服务端算完再传回来。这样你就明白了网络通信中“请求—响应”的完整链路也理解了为什么会有协议这层东西存在。1.2 为什么不用现成协议而是自己定义很多人会问计算器这种小工具直接用HTTPJSON不香吗香但项目目的不是做一个生产级计算器而是练手自定义协议。用HTTPJSON底层已经帮你解决了连接管理、报文格式、状态码这些问题你真正要学的套接字、粘包、序列化反而被掩盖了。自定义协议之后每一个细节都必须自己设计比如报文的边界在哪里收多少字节算一包是定长包头还是特殊分隔符数据用什么编码要不要考虑字节序怎么关联请求和响应如果客户端半路断开服务器怎么处理收到非法数据是直接断开还是返回错误码这些问题在现有的高级协议里都被封装掉了但恰恰是Linux网络编程里的核心能力。自定义协议可以让你把这些决策全走一遍以后再看HTTP、WebSocket这类协议时理解会深很多。1.3 适合谁参考这个项目适合三种人刚学完Linux socket编程想找一个能覆盖“协议设计并发处理调试技巧”的综合练习在学网络协议分析想通过一个实际小项目搞懂TCP粘包、字节序、端口复用等概念准备面试需要能够清晰讲出一个从零设计的网络通信项目的候选人。我实现的时候用的环境是Ubuntu 22.04编译器gcc代码是C语言调试用了nc、tcpdump和gdb。这些在Linux系统下都是常见工具跟着做不会卡在环境上。2. 协议设计先把“通信语言”定清楚2.1 自定义协议需要定义哪些内容写网络程序先别急着敲代码第一件事是定协议。协议就是通信双方约定好的一套规则一套网络版本的“计算器语言”。我的习惯是先用文字把这个语言定下来客户端发什么服务器回什么中间出错了怎么办。设计时要回答下面几个问题传输层用什么选TCP因为计算请求对可靠性要求高丢一个字节都可能算错。报文边界怎么区分TCP是字节流没有消息边界所以协议里必须带上长度信息。一条报文包含哪些字段至少要有头部标识、版本、类型、长度、正文表达式、校验。返回结果怎么表示要有成功和失败两种类型错误不能只靠断开连接表达。如何处理多个客户端协议层面只需要保证每个请求有唯一序列号这样客户端可以区分多个响应。这些设计完协议才算是立得住。不然代码写一半再补协议就得返工。2.2 我选的二进制协议格式我最终定义的协议是二进制格式头部固定8字节后面跟业务数据。用结构体描述就是下面这样#pragma pack(push, 1) typedef struct { uint8_t magic; // 魔数固定为0x5A用来快速过滤非法包 uint8_t version; // 协议版本当前为1 uint8_t type; // 包类型 uint8_t seq; // 序列号客户端自增 uint32_t length; // 数据区长度网络字节序 } calc_header; typedef struct { calc_header header; char data[]; // 变长数据 } calc_packet; #pragma pack(pop)头部固定8字节是因为8字节在64位系统上对齐比较方便而且字段少解析快。magic用0x5A收到第一个字节不是0x5A的包直接判定非法。version用于以后协议升级比如改成0x5B或者魔数变掉可以兼容处理。type定义请求和响应类型。我保留了几个枚举值enum { TYPE_CALC_REQ 0x01, // 客户端请求计算 TYPE_CALC_RESP 0x02, // 服务器返回计算结果 TYPE_ERROR_RESP 0x03 // 服务器返回错误 };seq是序列号客户端每次请求递增服务器原样返回。这样即使同一个TCP连接上连续发两个计算请求客户端也能分辨哪个响应对应哪个请求。length是数据区长度包含表达式或结果字符串的字节数。因为表达式允许变长所以这里必须显示指定。为了真实还原现场我补充一个完整的请求包示例。客户端发送“12*3”这串字符不带NULL结尾数据区长度就是5字节。整个包十六进制如下5A 01 01 01 00 00 00 05 31 2B 32 2A 33第1字节5A是魔数第2字节01是版本第3字节01是计算请求类型第4字节01是序列号第5-8字节是00 00 00 05也就是长度5的网络字节序。后面5个字节是ASCII字符“12*3”。响应包同样结构数据区是结果字符串比如“7”。2.3 粘包与拆包问题的预防TCP是流式协议没有天然的消息边界。发送端可能一次发送多个包接收端可能一次只收到半个包。这就是网络编程里最常见的“粘包/半包”问题。我选择固定头部长度字段来拆包这种方式思路清晰接收端先收满8字节头部。解析出length字段转成主机字节序。再等待接收length字节的数据区。如果length超出预设上限比如1024字节直接判定非法包并断开。代码层面我封装了一个函数专门负责从套接字读取一个完整的包。这里用recv循环接收直到读满期望字节数。static ssize_t read_full(int fd, void *buf, size_t len) { size_t got 0; char *p (char *)buf; while (got len) { ssize_t n recv(fd, p got, len - got, 0); if (n 0) { return -1; } got n; } return got; }读头部和读数据区都用这个函数。这样无论对端一次发一个包还是两个包代码都能正确处理。自定义协议里最重要的一句话就是永远不要假设一次recv能拿到完整报文。3. Linux端实现从套接字到计算引擎3.1 开发环境与工具选择我用的开发环境是Linux编辑器是vim编译用gcc调试用gdb。工程文件不复杂就三个源文件server.c服务器主逻辑负责网络监听、连接处理、调用协议编解码。proto.c协议编解码函数处理包头解析、校验长度、构造响应包。calc.c表达式解析和计算。编译命令很简单gcc -Wall -Wextra -O2 -g server.c proto.c calc.c -o calc_server加-g是为了配合gdb调试加-Wall和-Wextra是为了让编译器帮我盯着常见问题。做网络程序断开重连、端口被占用这些情况经常要靠日志来定位所以我预留了一个简单的日志打印避免全是printf裸奔。3.2 服务器端框架监听、接受、处理服务器端的基本步骤是标准四件套socket创建、bind绑定、listen监听、accept接受连接。端口我选了8000避免和常见服务冲突。int lfd socket(AF_INET, SOCK_STREAM, 0); int opt 1; setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, opt, sizeof(opt)); struct sockaddr_in addr; addr.sin_family AF_INET; addr.sin_addr.s_addr INADDR_ANY; addr.sin_port htons(8000); bind(lfd, (struct sockaddr *)addr, sizeof(addr)); listen(lfd, 128);这里特别要提SO_REUSEADDR。如果不设置它服务器刚退出又立刻重启时会因为TIME_WAIT状态而抓狂“Address already in use”。设置之后重启就没这个问题了这也是我实际踩过的坑之一。连接处理我用了多线程方式每个客户端accept之后创建一个线程去处理。Linux下最简单是pthread_createwhile (1) { int cfd accept(lfd, NULL, NULL); if (cfd 0) continue; pthread_t tid; pthread_create(tid, NULL, client_handler, (void *)(long)cfd); pthread_detach(tid); }用pthread_detach让线程结束自动释放资源不需要主线程回收。这里有个细节传给线程的cfd要先转成指针再传进去。如果直接传cfd多个客户端顺序accept时cfd变量会被覆盖后面的线程读到的可能不是自己那个连接。我单独分配了一份整数再传就避开了这个坑。3.3 自定义协议编解码实现协议编解码是自定义协议的核心工程。解析请求包时我按固定流程走调用read_full读8字节头部。检查magic是不是0x5A。检查version是不是当前版本。读取length字段用ntohl转成主机字节序。如果length为0或者超过上限断开。根据length读数据区。确保读到的数据区末尾补一个\0方便作为C字符串处理。这里还有一个容易忽略的点协议规定数据区不包含结束符但内存里加一个\0并不会破坏协议因为length已经说明了数据的边界。构造响应包时我会复用请求头的ver和seq这样客户端可以通过seq对应。响应包类型是TYPE_CALC_RESP或TYPE_ERROR_RESP。错误响应也走同一套报文格式方便客户端统一解析。ssize_t send_packet(int fd, uint8_t type, uint8_t ver, uint8_t seq, const char *data, uint32_t len) { char buf[1024] {0}; calc_header *hdr (calc_header *)buf; hdr-magic 0x5A; hdr-version ver; hdr-type type; hdr-seq seq; hdr-length htonl(len); if (len 0) memcpy(buf sizeof(calc_header), data, len); return send_all(fd, buf, sizeof(calc_header) len); }send_all和read_full类似也是循环发送防止一次性send没发完。网络编程里写数据也不能假设一次send就能把所有数据送走尤其数据量稍大时。3.4 表达式解析与计算服务器拿到表达式后计算逻辑是我单独封装的一层。这层的意思是只要协议变了或者客户端换语言计算逻辑都能独立复用。为了不算得太复杂我支持了四则运算、括号、小数点、负数还加了一个^幂运算。计算思路是中缀表达式转后缀表达式再用栈求值。这是最稳妥、最直观的实现方式比递归下降简单也比eval那种“查系统库”的方式更有学习价值。转换过程用两个栈一个栈放操作符一个队列实际用数组模拟放输出。运算符优先级定义int priority(char op) { switch (op) { case : case -: return 1; case *: case /: return 2; case ^: return 3; default: return 0; } }中缀转后缀的要点是遇到数字或小数点收集成完整的数字字符串。遇到左括号直接入操作符栈。遇到右括号操作符栈不断弹出并输出直到遇到左括号。遇到运算符弹出所有优先级不低于当前运算符的栈顶操作符再压入当前运算符。求值时从左到右扫描后缀表达式遇到数字压栈遇到运算符弹出两个操作数计算结果再压栈。这个逻辑我单独放在calc.c里不掺任何网络代码方便单元测试。有一个我一开始没做后来加上去的功能除零检查。除零时要返回错误码不能直接让float变成inf更不能让进程崩溃。服务器返回错误报文时数据区放一个人类可读的提示比如“divide by zero”客户端就能直接显示给用户。3.5 客户端实现与测试客户端代码比服务器简单得多创建socketconnect到服务器发送请求包读取响应包按同样的协议拆包把数据区打印出来。这里我做了个循环支持从终端输入一行表达式就发送一次直到输入quit退出。客户端的关键代码int cfd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in saddr; saddr.sin_family AF_INET; saddr.sin_port htons(8000); inet_pton(AF_INET, 127.0.0.1, saddr.sin_addr); connect(cfd, (struct sockaddr *)saddr, sizeof(saddr)); uint8_t seq 0; char expr[512]; while (fgets(expr, sizeof(expr), stdin)) { if (strncmp(expr, quit, 4) 0) break; // 去掉换行符 expr[strcspn(expr, \n)] 0; uint32_t len strlen(expr); // 构造请求包并发送 send_packet(cfd, TYPE_CALC_REQ, 1, seq, expr, len); // 解析响应包 calc_packet *resp recv_packet(cfd); printf(result: %.*s\n, resp-header.length, resp-data); }我测试时测了这些表达式输入期望结果12*37(12)*3910-2^325/0divide by zero2*(34)14-352其中-35这种负数开头转换算法里要特殊处理如果表达式开头是负号我补一个0变成0-35这样结果就是2。这个细节容易漏实际测试时发现了补进去之后逻辑才稳。客户端测通之后整个“Linux 自定义协议 网络计算器”主链路就算跑通了。接下来最花时间的其实是调试。4. 调试技巧与常见问题4.1 用nc做协议联调写代码时不一定非要先写客户端才能测服务器。我推荐一个调试利器ncnetcat。在没有客户端的情况下直接手工拼接一个请求包发给服务器看返回。比如我是这么做的printf \x5A\x01\x01\x01\x00\x00\x00\x05\x31\x2B\x32\x2A\x33 | nc 127.0.0.1 8000 | xxd输出会显示服务器回了一个8字节头部加一个字节结果。如果服务器没反应就要检查监听端口、防火墙和协议格式。如果不想手写二进制也可以先启动服务器再打开两个终端一个用nc监听一个本地端口模拟客户端另一个发数据。总之nc能帮你把“网络传输”和“程序逻辑”分开排查先用nc确认能连上、能发数据再怀疑代码里的问题。4.2 字节序和结构体对齐问题自定义二进制协议最经典的坑就是字节序。x86是小端序而网络规定用大端序。所以协议头里的length字段我用htonl存储解析时用ntohl。如果不转换客户端和服务器在同一台机器上可能碰巧能跑但一旦跨架构比如客户端在ARM板子上服务器在x86机器上长度字段就直接错了。结构体对齐是第二个坑。calc_header只有8字节但在默认对齐下加上后面变长数据可能出问题。所以我在定义时加了#pragma pack(push, 1)强制按1字节对齐。如果你偷懒不写用一个sizeof(calc_header)取包头长度真实占用可能变成12字节甚至更多后面所有计算全乱。这里强烈建议二进制协议的定义要么手写字节缓冲区自己填充要么用packed结构体但明确知道它的占用。千万别拿默认对齐的结构体直接send。4.3 并发压力与半包处理多客户端并发时主要问题有几种多个线程同时accept要保证accept调用是线程安全的实际上Linux下accept是可重入的同一个listen fd多线程accept没问题但为了简单我选择主线程单accept工作线程处理连接。半包问题在并发下更容易出现。因为多个客户端同时发数据recv可能收到不同客户端的数据不会TCP连接是独立的每个fd一个连接不会混。但同一个连接的多个包可能粘在一起这就要靠拆包逻辑。服务器需要防呆如果客户端只发了4个字节就断开read_full会在第二次recv时返回0或者-1处理线程必须能退出而不是死循环。我还用脚本模拟了100个并发连接每个连接随机发送若干表达式。跑完之后统计响应数量确认没有丢包。for i in $(seq 1 100); do printf \x5A\x01\x01\x%02x\x00\x00\x00\x03\x31\x2B\x31 $i | nc 127.0.0.1 8000 /tmp/resp.log done wait wc -l /tmp/resp.log这里%02x会生成不同seq每次连接只有一个请求。因为nc每次只发送一次就关闭所以日志里应该有一百行响应。如果少于100就说明服务器有accept之前就丢连接或者处理中出现异常退出的情况。4.4 我踩过的几个坑这个项目我踩的坑列成表格给后来人参考问题现象原因解决服务器重启报Address already in use没设置SO_REUSEADDR加上setsockopt表达式返回结果错乱length字段没有用ntohl解析统一用htonl/ntohl客户端发完请求服务器收不到没有循环recv一次只读了几字节封装read_full请求包尾部多了垃圾数据直接strlen后发送字符串里带换行用strcspn去掉换行nc测出响应包长度不对结构体对齐导致sizeof大于8加#pragma pack(1)处理线程崩溃导致整个进程退出对端断开时send触发SIGPIPEsignal(SIGPIPE, SIG_IGN)SIGPIPE这个问题很隐蔽当客户端关闭连接后服务器如果继续send内核会向进程发送SIGPIPE信号默认行为是终止进程。测试时我明明只开了一个客户端关掉后再来一个请求服务器直接退出。后来在main里加了一句signal(SIGPIPE, SIG_IGN);之后再遇到对端断开send只是返回-1由代码逻辑去处理进程不会莫名死掉。5. 怎么扩展成可用项目5.1 协议版本兼容现在的协议版本字段是1。以后如果我想改变包格式不用完全推翻重来。可以在解析时判断version如果是1走老逻辑如果是2走新逻辑。如果客户端版本比服务器高服务器可以返回一个不支持的响应。系统升级时老客户端还能短暂兼容这个字段的价值就在这里。还有一个思路是扩展type类型。比如加一个TYPE_PING_REQ心跳包用来做保活检测。服务器收到心跳后返回TYPE_PING_RESP客户端可以靠它判断连接是否仍然有效。对于长时间不发送表达式的情况心跳能防止中间设备把空闲连接回收掉。5.2 日志与监控我之前直接printf打日志一个客户端连接结束也只能在终端里翻。后来我把日志改成写入文件并且给每个连接打上唯一的连接ID。这样排查问题时可以按连接ID筛选定位某个客户端经历了什么。监控指标我建议记录几类每秒处理的请求数当前活跃连接数平均响应延迟协议解析失败次数。这些指标不需要上复杂系统直接写到日志文件再用awk统计。比如统计连接数grep accept /tmp/calc_server.log | wc -l有了这些哪怕只是练习项目也能养成运维意识。5.3 安全与校验自定义协议最大的风险就是没有防护。我的项目里只做了一件事限制数据区长度。超过1024字节直接拒绝。否则客户端发一个超大length字段服务器就会傻傻地等待接收超大报文把内存吃满。更严格一点应该在校验字段上做文章。我这里头部没有加校验只是魔数过滤。其实可以加一个两字节的CRC16放在length后面。接收端先校验CRC校验失败就丢弃。我加校验之后随意篡改一个字节也能被我抓到。实际项目里尤其是工业远程控制类场景这种“消息指纹”几乎必备。还有一点自定义协议默认不加密如果是在不可信网络上传输表达式和结果都可能被嗅探。生产环境中要么把整个通信封装在加密隧道里要么在协议层做加密。但作为Linux练习项目明白这一点就够了不要真的对公网开放。做这个小项目最值的一点把“Linux 自定义协议 网络计算器”整个折腾完我最大的感受是复杂协议没那么玄乎核心就是“定好字节、定好边界、管好异常”。很多书上学的时候觉得碎片化的概念比如字节序、粘包、并发、SIGPIPE在这个项目里一条线全部串起来了。后面再去看HTTP、MQTT这种协议你会发现它们本质上也是在一个消息外加了固定格式的头部只是规范更完整、扩展字段更多。如果你也想练自定义协议建议从更小的玩意儿改起把你的计算器协议从二进制改成纯文本或者加一个登录认证字段。改一次你就知道协议设计时留那几个字段有多重要了。我甚至回头翻了当时自己定的第一版协议发现没有seq字段导致连续发两个请求时分不清响应立刻补了上去。这就是自定义协议的乐趣你踩过的每个坑都会变成协议版本号后面的那一个commit。

相关新闻

数据工程容器化实践:从开发环境到生产调度的全链路改造

数据工程容器化实践:从开发环境到生产调度的全链路改造

1. 为什么数据工程越来越离不开容器化1.1 数据工程团队里最常见的那些闹心场面先说我自己的经历。早些年我在一家中型公司做数据平台,当时团队维护的是一套比较传统的 Hadoop 集群,Hive、Spark、Flink 都有部署,环境由运维统一管理。每次有新…

2026/10/9 3:12:59 阅读更多 →
LeetCode 138随机链表复制:五种解法与深拷贝要点

LeetCode 138随机链表复制:五种解法与深拷贝要点

如果你刷过LeetCode热门100题,或者最近在集中准备算法面试,大概率会在题单里撞见这道#138 随机链表的复制。我第一次做它是在模拟面试现场,心里想的是“复制个链表谁不会?new一个新节点、把next串起来不就行了?”结果写…

2026/10/9 3:11:59 阅读更多 →
Java机器学习分布式故障诊断系统:从数据采集到在线推理的工程实践

Java机器学习分布式故障诊断系统:从数据采集到在线推理的工程实践

简介:这份源码资源面向具备一定Java基础、希望将机器学习落地到运维场景的开发者与高校学生,聚焦分布式系统故障诊断这一典型问题。项目以Java为主语言实现,结合机器学习算法对分布式环境下的异常进行识别与分类,可用于课程设计、…

2026/10/9 3:11:59 阅读更多 →

最新新闻

HermesWorkspace Playground 可选 3D NPC 模型替换指南:基于 GLB 的 Voxel 身体升级方案

HermesWorkspace Playground 可选 3D NPC 模型替换指南:基于 GLB 的 Voxel 身体升级方案

【免费下载链接】hermes-workspace Native web workspace for Hermes Agent — chat, terminal, memory, skills, inspector. 项目地址: https://gitcode.com/gh_mirrors/he/hermes-workspace 点击查看 免费下载 本文依据仓库 public/avatars-3d/README.md 编写&am…

2026/10/9 4:47:02 阅读更多 →
C++实现逆波兰表达式的例题详解

C++实现逆波兰表达式的例题详解

1. 题目描述2. 解题思路逆波兰表达式由波兰的逻辑学家卢卡西维兹提出,它的特点是:没有括号,运算符总是放在和它相关的操作数之后。因此,逆波兰表达式也称后缀表达式,它严格遵循「从左到右」的运算。在我们平时生活中&a…

2026/10/9 4:47:02 阅读更多 →
TaoToken 统一 Key 接入:Top 20 代码生成 LLM 在 Three.js 与 YOLO 工作流中的选型清单

TaoToken 统一 Key 接入:Top 20 代码生成 LLM 在 Three.js 与 YOLO 工作流中的选型清单

/* 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 4:47:02 阅读更多 →
A股个人量化软件推荐:三款工具的仓位与交易规则

A股个人量化软件推荐:三款工具的仓位与交易规则

个人验证A股交易规则,可以比较BigQuant、牛股王股票和米筐在线量化平台。希望把筛选结果转成目标仓位并研究交易逻辑,了解BigQuant;希望配置持股数量、单票仓位及退出规则,检查牛股王股票中的智擎 AT 系统;希望用Pytho…

2026/10/9 4:47:02 阅读更多 →
Azure Cost Management Forecast API 请求体 Schema 完全指南:从字段解析到实战调用

Azure Cost Management Forecast API 请求体 Schema 完全指南:从字段解析到实战调用

【免费下载链接】autoskills One command. Your entire AI skill stack. Installed. 项目地址: https://gitcode.com/gh_mirrors/au/autoskills 点击查看 免费下载 导读 本文围绕 autoskills 仓库中 azure-cost 技能包(azure-cost)的 Forec…

2026/10/9 4:47:02 阅读更多 →
openrig 配置管理:统一 Claude Code 与 Codex 的 YAML 方案

openrig 配置管理:统一 Claude Code 与 Codex 的 YAML 方案

1. 从 openrig 说起:一个被名字耽误的配置管理思路第一次看到 openrig 这个词,很多人会以为是某个硬件外设品牌,或者某个开源机械臂项目。但如果你最近在折腾 Claude Code、Codex 这类命令行 AI 编程工具,又恰好被各种 YAML 配置、…

2026/10/9 4:46:02 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

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/8 15:26:32 阅读更多 →
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/8 15:26:40 阅读更多 →
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/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 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/8 21:13:17 阅读更多 →
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/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练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/7 13:34:55 阅读更多 →