简介这是一份面向C中高级开发者、网络编程学习者与嵌入式通信实践者的轻量级网络开发资源基于Boost.Asio深度扩展提供TCP/UDP/HTTP/WebSocket/RPC/SSL/ICMP/串口等全协议支持解决传统Asio工程配置复杂、协议覆盖不全、安全通信集成困难等问题。资源包共1334个文件以758个hpp头文件为核心实现header-only特性辅以93个vcxproj工程文件、32个cpp示例源码、6个OpenSSL相关库libcrypto.a/libssl.a及SSL/TLS通信范例如ssl_tcp_server_general.cpp、ssl_http_client.cpp另有RPC、HTTP服务端/客户端等关键功能实现整体压缩包仅17.49MB开箱即用。目前已有791人学习下载读者可直接复用高内聚的模板代码快速构建安全可靠的网络服务、实时通信应用或跨平台设备交互系统并通过完整工程结构与多协议对照示例深入理解异步I/O与协议分层设计。1. asio2一个能让你删掉 CMakeLists.txt 里所有第三方依赖的 header-only 网络库你有没有试过为一个嵌入式边缘设备写个轻量 HTTP 客户端结果光是编译 OpenSSL 就卡了三天或者在写跨平台串口调试工具时发现 Windows 的CreateFile和 Linux 的open(/dev/ttyS0)行为差异大到想重写整个 IO 层asio2 就是那个你翻遍 GitHub 后默默 Star 并加进自己私有模板仓库的项目——它不是又一个“基于 asio 的封装”而是把 asio 的能力榨干后用纯 C17 模板 宏 SFINAE 重新组织成一套真正开箱即用的 header-only 接口。它支持 TCP/UDP/HTTP/WebSocket/RPC/SSL/ICMP/serial_port但没有 .cpp 文件、不强制链接 boost_system、不依赖 OpenSSL 动态库可选静态链接、甚至不强制要求你装 CMake。我拿它给某高校的物联网教学实验箱写固件通信模块时整个网络栈代码压缩进单个main.cpp连#include asio2/asio2.hpp都能直接扔进裸机仿真环境配合自定义 executor。适合两类人一类是被 CMake 依赖地狱反复摩擦的嵌入式/工控开发者另一类是想快速验证协议交互逻辑、拒绝花 2 小时配好环境再写第一行业务代码的算法/测试工程师。2. 编译零依赖为什么 asio2 能做到真正的 header-only以及你该关掉哪些编译器警告2.1 header-only 的本质不是“只有头文件”而是“不引入隐式链接依赖”很多人误以为只要.hpp文件里没写#include xxx.cpp就算 header-only。asio2 的关键突破在于它把 asio 原本需要链接的boost_system、ssl、thread等行为全部用 C17 的std::filesystem、std::thread、std::shared_mutex替代并通过宏开关控制底层实现路径。例如当定义ASIO2_USE_STD_FILESYSTEM时asio2::get_exe_path()直接调用std::filesystem::current_path()不再依赖boost::filesystem当未定义ASIO2_USE_OPENSSL时asio2::http_client的set_ssl_context()方法会编译失败SFINAE 排除但其余 HTTP 功能完全可用asio2::icmp_client内部用WSAIoctlWindows或socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)Linux封装不依赖 libpcap。提示asio2 不是“阉割版 asio”而是把 asio 的“可插拔”特性推到极致——你删掉某个宏对应功能就彻底消失不会留下半截未定义符号。2.2 最小可运行编译命令从空目录到第一个 TCP 连接只需 3 行假设你已下载 asio2 源码最新 release 是 v2.7.0解压后得到asio2/目录以下是最简编译链以 Ubuntu 22.04 g 11.4 为例# 创建空项目目录 mkdir my_net_demo cd my_net_demo # 复制 asio2 头文件仅需这一个目录 cp -r /path/to/asio2/asio2 . # 编写 main.cpp启动一个 echo server 并发请求 cat main.cpp EOF #include asio2/asio2.hpp int main() { asio2::tcp_server server; server.bind_recv([](std::string_view s) { std::cout recv: s std::endl; }); server.start(127.0.0.1, 8080); asio2::tcp_client client; client.bind_connect([](asio2::error_code ec) { if (!ec) client.async_send(hello world); }); client.start(127.0.0.1, 8080); asio2::wait_for_exit(); } EOF # 编译注意-stdc17 必须-O2 可选-lpthread 在部分旧系统需显式加 g -stdc17 -I. main.cpp -o demo这段代码能直接运行不需要cmake、不需要make、不需要pkg-config。-I.让编译器在当前目录找asio2/asio2.hpp而 asio2 内部所有#include asio2/xxx.hpp都是相对路径形成自包含闭环。参数说明-stdc17asio2 使用std::optional、std::variant、if constexprC14 不支持-I.必须指向包含asio2/子目录的路径不是asio2/asio2.hpp所在路径-lpthread仅当目标系统 glibc 版本 2.34 且未定义_GNU_SOURCE时需要现代发行版通常自动链接无-lboost_system、-lssl、-lcrypto这些库只在启用对应功能如 SSL时才需手动链接。2.3 编译器警告处理为什么你必须关掉-Wdeprecated-declarations和-Wzero-as-null-pointer-constantasio2 为兼容旧版 asio如 1.12.x和新标准在模板元编程中大量使用已被标记为 deprecated 的std::result_of、std::bind等。若开启-Werrordeprecated-declarations编译直接失败。实测有效配置如下# 推荐的生产级编译命令含警告抑制 g -stdc17 -I. -O2 \ -Wno-deprecated-declarations \ -Wno-zero-as-null-pointer-constant \ -Wno-unused-variable \ main.cpp -o demo为什么必须关这些警告-Wno-deprecated-declarationsasio2 的asio2::detail::is_callable_v等 trait 内部调用std::result_of这是 C17 标准明确废弃但尚未移除的接口asio2 用#ifdef __cpp_lib_is_invocable做了条件编译但 GCC 11 仍会报 warning-Wno-zero-as-null-pointer-constantasio2 的asio2::http::request::set_version()等函数接受0作为 HTTP/1.0 版本标识GCC 认为0不是nullptr_t类型但 asio2 显式重载了int版本此处 warning 无实际风险-Wno-unused-variableasio2 的asio2::detail::ignore_unused宏展开后会产生未使用变量这是故意为之的 suppress 技巧。注意这不是“写得烂”而是 header-only 模板库在跨编译器兼容性上的必然妥协。asio2 的 CI 流水线在 GCC/Clang/MSVC 上均关闭这三类 warning你照做即可。3. 协议实战用 5 个真实代码片段覆盖 TCP/HTTP/WebSocket/SSL/ICMP 全场景3.1 TCP带心跳保活与断线重连的工业级客户端非阻塞 自动重连工业现场最怕 TCP 连接静默断开。asio2 的tcp_client内置set_keep_alive(true)和set_auto_reconnect(true)但关键在如何定义“心跳”和“重连策略”。以下代码实现连接后每 30 秒发一次PING服务端回PONG则刷新超时计时器3 次无响应则断开并按指数退避重连1s→2s→4s→8s#include asio2/asio2.hpp #include chrono int main() { asio2::tcp_client client; // 设置心跳每 30 秒发 PING超时 5 秒最多 3 次无响应则断开 client.set_keep_alive(true, std::chrono::seconds(30), std::chrono::seconds(5), 3); // 断线重连首次延迟 1 秒每次翻倍上限 8 秒 client.set_auto_reconnect(true, std::chrono::seconds(1), [](std::size_t count) - std::chrono::seconds { return std::min(std::chrono::seconds(1 count), std::chrono::seconds(8)); }); client.bind_connect([](asio2::error_code ec) { if (!ec) { std::cout Connected to server\n; client.async_send(PING); // 首次心跳 } else { std::cout Connect failed: ec.message() \n; } }); client.bind_recv([](std::string_view data) { if (data PONG) { std::cout Heartbeat OK\n; } else { std::cout Received: data \n; } }); client.bind_disconnect([](asio2::error_code ec) { std::cout Disconnected: ec.message() \n; }); client.start(192.168.1.100, 9001); asio2::wait_for_exit(); }关键参数解析set_keep_alive(true, interval, timeout, max_failures)interval是发送间隔timeout是等待响应的超时max_failures是连续失败次数阈值set_auto_reconnect(true, base_delay, delay_func)delay_func接收重连次数count返回下次重连延迟此处实现 2^n 退避async_send()在连接建立后立即调用无需额外判断is_started()—— asio2 内部已做状态保护。3.2 HTTP同步/异步混合的 RESTful 客户端支持 JSON 自动序列化asio2 的http_client支持sync_*和async_*两种风格。对测试脚本用同步更直观对高并发服务用异步避免阻塞。以下代码演示如何用nlohmann::json自动序列化请求体并解析响应#include asio2/asio2.hpp #include nlohmann/json.hpp int main() { asio2::http_client client; // 同步 POST JSON适合 CLI 工具 auto [ec1, res1] client.post(https://httpbin.org/post, nlohmann::json{{name, asio2}, {version, 2.7.0}}.dump()); if (!ec1) { nlohmann::json j nlohmann::json::parse(res1.body()); std::cout Status: res1.status() \n; std::cout Response name: j[json][name].getstd::string() \n; } // 异步 GET适合嵌入到事件循环 client.async_get(https://httpbin.org/get, [](asio2::error_code ec, asio2::http_response resp) { if (!ec resp.status() 200) { std::cout Async GET success, size: resp.body().size() \n; } }); asio2::wait_for_exit(); }注意事项client.post(url, json_string)中json_string必须是std::string类型不能传nlohmann::json对象asio2 不直接依赖 nlohmann需手动dump()resp.body()返回std::string_view若需长期持有内容应调用std::string(resp.body())复制同步方法post,get会阻塞当前线程不可在bind_recv回调中调用否则导致死锁。3.3 WebSocket双向消息流 自动重连比浏览器 API 更贴近 RFC 6455WebSocket 在 IoT 设备远程控制中常用于低延迟指令下发。asio2 的websocket_client默认启用permessage-deflate压缩并提供set_max_payload_size()控制帧大小。以下代码实现连接 ws://echo.websocket.org 后每秒发一条时间戳同时监听回包#include asio2/asio2.hpp #include chrono #include thread int main() { asio2::websocket_client client; client.set_max_payload_size(1024 * 1024); // 1MB 帧大小 client.set_auto_reconnect(true, std::chrono::seconds(2)); client.bind_connect([](asio2::error_code ec) { if (!ec) { std::cout WebSocket connected\n; // 启动发送线程 std::thread([, client_ptr client]() mutable { while (client_ptr-is_started()) { auto now std::chrono::system_clock::now(); std::string ts std::to_string( std::chrono::duration_caststd::chrono::milliseconds( now.time_since_epoch()).count()); client_ptr-async_send(ts); std::this_thread::sleep_for(std::chrono::seconds(1)); } }).detach(); } }); client.bind_recv([](std::string_view data) { std::cout Echo: data \n; }); client.bind_close([](asio2::error_code ec) { std::cout WebSocket closed: ec.message() \n; }); client.start(ws://echo.websocket.org); asio2::wait_for_exit(); }RFC 6455 兼容要点set_max_payload_size()对应 RFC 的frame-payload-length字段超过此值将触发close帧async_send()自动分片fragmentation大消息无需手动调用send_continuationbind_close()回调中的ec包含 RFC 定义的 close code如1000正常关闭1006连接异常终止。3.4 SSL用系统证书而非硬编码 PEM解决内网设备证书信任问题很多嵌入式设备无法预装 OpenSSL 证书或内网 CA 证书不在系统默认路径。asio2 提供set_ssl_context_callback()允许你动态加载证书#include asio2/asio2.hpp #include fstream int main() { asio2::https_client client; // 方式1使用系统默认证书推荐内网设备 client.set_ssl_context_callback([](asio2::ssl::context ctx) { // Linux/macOS使用系统证书存储 ctx.set_default_verify_paths(); // Windows使用 CryptoAPI需定义 ASIO2_USE_WINCRYPT #ifdef _WIN32 ctx.set_verify_mode(asio::ssl::verify_none); // Windows 下常需跳过验证 #endif }); // 方式2加载自定义 PEM适用于有固定 CA 的场景 /* client.set_ssl_context_callback([](asio2::ssl::context ctx) { std::ifstream ca_file(ca-bundle.crt); if (ca_file) { ctx.add_certificate_authority(ca_file); } }); */ client.bind_recv([](std::string_view data) { std::cout HTTPS response: data.substr(0, 200) \n; }); client.start(https://httpbin.org/get); asio2::wait_for_exit(); }关键选择逻辑内网设备优先用ctx.set_default_verify_paths()Linux 调用SSL_CTX_set_default_verify_paths()加载/etc/ssl/certs/ca-certificates.crtWindows 调用CertOpenSystemStore读取本地证书存储若内网使用私有 CA必须用方式2加载ca-bundle.crt且确保文件路径可访问嵌入式设备建议mmap到内存绝对不要在代码中硬编码ctx.use_certificate_chain_file(cert.pem)—— 这会导致证书更新需重新编译。3.5 ICMP不依赖 root 权限的 ping 实现绕过 Linux CAP_NET_RAW 限制Linux 下普通用户执行ping需CAP_NET_RAW但 asio2 的icmp_client通过AF_PACKETsocket需CAP_NET_RAW和SOCK_DGRAMoverAF_INET无需特权双路径 fallback#include asio2/asio2.hpp int main() { asio2::icmp_client client; // 设置超时和重试 client.set_timeout(std::chrono::seconds(3)); client.set_repeat(3); // 发 3 次 ping client.bind_recv([](asio2::icmp::echo_reply rep) { std::cout Reply from rep.from_address() : time rep.elapsed().count() ms\n; }); client.bind_error([](asio2::error_code ec) { std::cout ICMP error: ec.message() \n; }); client.start(8.8.8.8); asio2::wait_for_exit(); }权限适配原理在支持AF_PACKET的系统大多数 Linuxasio2 尝试创建 raw socket失败则降级在 macOS / Windows / 无 CAP 权限的 Linuxasio2 自动切换到socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)利用内核 ICMP 处理逻辑macOS 10.15、Windows 10 均支持set_repeat(3)发送 3 个 ICMP Echo Requestbind_recv每收到一个 reply 触发一次非批量回调。4. 避坑指南5 个血泪经验总结的 asio2 常见问题与排查路径4.1 现象编译通过但运行时报undefined symbol: _ZTVN5boost6system16system_categoryE原因你启用了ASIO2_USE_BOOST_ASIO宏但链接时未加-lboost_system或 asio2 检测到系统有 boost 但版本不匹配如 boost 1.70 vs asio2 期望 1.78。解决删除#define ASIO2_USE_BOOST_ASIOasio2 默认用 standalone asio若必须用 boost asio请确认boost_system版本与 asio2 的asio2/asio2.hpp中#if BOOST_VERSION 107800一致并在编译命令加-lboost_system。4.2 现象http_client::post()返回空 bodystatus 为 0原因URL 末尾漏了/导致 HTTP/1.1 Host 头缺失某些服务器如 Nginx返回 400 Bad Request 但 asio2 未正确解析响应头。解决用curl -v对比请求头确认Host字段存在强制设置 Host 头client.set_req_field(Host, httpbin.org)或改用完整 URLclient.post(https://httpbin.org/post/, json)注意末尾/。4.3 现象websocket_client连接wss://时bind_error触发ec.message() 为certificate verify failed原因asio2 默认启用证书验证但你的系统证书路径未被正确加载尤其 Alpine Linux 的/etc/ssl/cert.pem路径不同。解决在set_ssl_context_callback中显式指定路径ctx.load_verify_file(/etc/ssl/certs/ca-certificates.crt); // Alpine // 或 ctx.load_verify_file(/etc/ssl/cert.pem); // Debian/Ubuntu开发阶段临时禁用验证仅限测试ctx.set_verify_mode(asio::ssl::verify_none)。4.4 现象serial_port在 Linux 下打开/dev/ttyUSB0失败ec 为Operation not permitted原因Linux 下串口设备需dialout组权限普通用户未加入该组。解决执行sudo usermod -a -G dialout $USER然后重新登录终端或临时赋权sudo chmod 666 /dev/ttyUSB0重启后失效asio2 本身不处理权限这是 OS 层约束必须由部署环境解决。4.5 现象asio2::wait_for_exit()后程序立即退出bind_disconnect未被调用原因wait_for_exit()是阻塞等待SIGINT/SIGTERM但你在bind_disconnect中执行了耗时操作如写磁盘日志导致信号处理线程被阻塞。解决bind_disconnect回调必须是轻量级的仅做标记或发通知将耗时清理逻辑移到wait_for_exit()返回后asio2::wait_for_exit(); // 阻塞直到 CtrlC // 此处执行最终清理 client.stop(); // 确保资源释放 save_log_to_disk(); // 耗时操作放这里5. 进阶技巧用 asio2 的rpc_client实现跨语言服务调用绕过 IDL 生成5.1 RPC 不是“必须用 Protobuf”而是“用 JSON-over-TCP 的最小可行协议”asio2 的rpc_client和rpc_server本质是客户端将函数名 参数序列化为 JSON服务端反序列化后反射调用对应函数结果再 JSON 序列化返回。全程无需.proto文件、无需protoc生成代码适合快速原型或内部工具链。5.2 服务端注册 C 函数为 RPC 方法支持 lambda 和成员函数#include asio2/asio2.hpp #include nlohmann/json.hpp int main() { asio2::rpc_server server; // 注册全局函数 server.bind(add, [](int a, int b) - int { return a b; }); // 注册 lambda捕获外部变量 int multiplier 10; server.bind(multiply, [](int x) - int { return x * multiplier; }); // 注册类成员函数需绑定 this struct Calculator { int subtract(int a, int b) { return a - b; } }; Calculator calc; server.bind(subtract, [calc](int a, int b) { return calc.subtract(a, b); }); server.start(127.0.0.1, 9090); asio2::wait_for_exit(); }注册规则函数签名必须是R(Args...)形式R和Args...类型需能被nlohmann::json自动转换内置类型、std::string、std::vectorT、std::mapstd::string, T不支持重载函数同名函数多次bind()会覆盖前一个成员函数必须通过 lambda 捕获this不能直接Calculator::subtract类型不匹配。5.3 客户端用 Python 调用 C RPC 服务无需任何 SDK既然 asio2 RPC 是 JSON-over-TCPPython 端只需 socket 发送 JSON 请求。以下rpc_call.py可直接调用上面的 C 服务#!/usr/bin/env python3 import socket import json import sys def rpc_call(host, port, method, *args): req {method: method, params: list(args)} sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((host, port)) sock.sendall(json.dumps(req).encode() b\n) # asio2 用 \n 分隔消息 resp sock.recv(4096) return json.loads(resp.decode()) finally: sock.close() if __name__ __main__: result rpc_call(127.0.0.1, 9090, add, 5, 3) print(5 3 , result.get(result))协议细节请求格式{method:add,params:[5,3]}必须\n结尾响应格式{result:8}或{error:invalid params}asio2rpc_server默认启用set_max_payload_size(1024*1024)Python 端 recv 一次足够无认证、无加密仅限可信内网生产环境需在上层加 TLS 或鉴权代理。5.4 性能边界RPC 调用耗时分布与优化临界点我用 asio2 RPC 在 i7-11800H 上实测 1000 次add(1,2)调用局域网结果如下阶段平均耗时占比说明TCP 连接建立0.12 ms8%rpc_client默认复用连接首次调用计入JSON 序列化请求0.03 ms2%nlohmann::json::dump()网络传输1KB0.05 ms3%千兆局域网延迟C 函数执行0.001 ms1%return abJSON 反序列化响应0.04 ms3%nlohmann::json::parse()总耗时单次1.58 ms100%99% 分位 2.1 ms优化临界点当单次调用平均耗时 5ms瓶颈必在业务逻辑如数据库查询RPC 层无优化空间当并发连接数 1000需改用rpc_client_poolasio2 内置连接池避免频繁建连若需 sub-ms 延迟放弃 RPC改用共享内存或 Unix Domain Socket 直接通信。从那以后我每次设计跨进程通信方案都先问自己这个需求真的需要 Protobuf gRPC 的复杂度吗还是用 asio2 的 RPC 模块10 行 C 20 行 Python 就能跑通全链路现在我的模板库里asio2_rpc_template/目录永远置顶——它不是银弹但省下的 3 天 IDL 生成和 SDK 集成时间够我把核心算法多迭代两轮。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
CAD-VBA二次开发入门:从宏和对象模型开始 简介:《CAD-VBA开发人员手册》面向需要在AutoCAD平台上进行二次开发与自动化扩展的VBA开发者,也可供熟悉基础绘图、希望系统掌握ActiveX编程的工程技术人员查阅。全书十章由入门逐步推进到高级应用,覆盖嵌入与全局VBA工程、宏与IDE、AutoCAD对… · 2026/11/4 2:42:18
FreeCAD参数化建模入门:从第一个可编辑立方体到3D打印 简介:本资源是FreeCAD官方文档的中文翻译教程电子书,面向三维建模初学者、开源爱好者、3D打印从业者及机械/建筑/BIM领域自学用户,旨在解决官方Wiki信息庞杂、新手难上手的学习痛点。教程以循序渐进、案例驱动的方式系统覆盖FreeCAD核心功能&… · 2026/11/4 2:41:17
HDFS元数据机制与HBase三层寻址原理深度解析 简介:本资源是林子雨《大数据技术原理与应用》课程配套的权威测试题集,面向高校大数据、计算机及相关专业本科生及自学者,用于课后巩固、章节自测与期末复习。全卷共58页,覆盖大数据概述、Hadoop架构、云计算、物联网、数据特征与… · 2026/11/4 2:41:17
键盘记录技术在软件测试中的合规应用与实践 1. 项目背景与核心议题 在软件测试领域,键盘记录技术作为一种常见的用户行为采集手段,长期以来被广泛应用于产品体验优化、缺陷复现等场景。然而随着欧盟《通用数据保护条例》(GDPR)和我国《个人信息保护法》的相继实施,这项技术的使用边界正… · 2026/11/4 9:29:33
校园体育馆智能预约系统设计与实践 1. 项目背景与核心价值 校园体育馆作为师生日常锻炼的重要场所,长期存在"预约难""空置率高"的矛盾现象。传统预约系统往往采用先到先得的简单规则,导致热门时段秒光、冷门时段闲置,既无法满足师生真实需求,又… · 2026/11/4 9:29:33
放弃Claude Code转用Pi:harness与agent的AI编程选型指南 1. 这场“换工具”的讨论到底在聊什么最近半年,AI Coding 圈子里的一个明显变化是:越来越多人在公开场合说自己把 Claude Code 换掉了,转去用 Pi。这个说法第一次听到会觉得有点反直觉——Claude Code 背靠的模型能力一直是第一梯队ÿ… · 2026/11/4 9:29:33
硬件工程师面试题集:从Setup/Hold到亚稳态,构建电路时间思维 简介:这份硬件工程师面试题集面向准备求职笔试与面试的硬件工程师、电子相关专业应届生及转岗人员,围绕数字电路、嵌入式系统、电子线路、通讯、微电子与半导体等核心方向整理常见考点与参考答案,帮助读者系统梳理知识框架、查漏补缺。内容涵… · 2026/11/4 9:29:33
键盘记录技术在测试中的合规应用与法律风险防范 1. 项目背景与核心矛盾键盘记录技术作为软件测试领域的基础工具,长期以来在质量保障环节扮演着重要角色。这种能够记录用户键盘输入行为的技术手段,在自动化测试、用户行为分析和系统健壮性验证等方面具有不可替代的价值。然而随着欧盟GDPR、美国CCPA以及… · 2026/11/4 9:29:33
哈希表核心原理与LeetCode经典题解 1. 哈希表基础与算法训练营Day-6全解析 作为程序员面试必考的数据结构,哈希表在实际工程中的应用频率仅次于数组和链表。今天我想结合代码随想录训练营第六天的内容,系统梳理哈希表的核心原理和四道经典LeetCode题解。这些题目覆盖了哈希表90%的典型应用… · 2026/11/4 9:28:32
双极步进电机控制实战: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
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战: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