当前位置: 首页 > article >正文

嵌入式Telnet服务器库:轻量级MCU远程调试方案

1. TelnetServer 库概述TelnetServer 是一个轻量级、可移植的嵌入式 Telnet 服务器实现库专为资源受限的 MCU 环境设计。它不依赖 POSIX socket API 或完整 TCP/IP 协议栈抽象层如 LwIP 的 netconn 接口而是直接对接底层网络驱动的 raw API如 LwIP 的tcp_pcb和回调函数机制以最小化内存开销与上下文切换延迟。其核心目标是在 STM32F4/F7/H7、ESP32、NXP RT1064 等典型 Cortex-M 平台下以 ≤ 4KB Flash ≤ 1.5KB RAM 的增量资源占用提供稳定、可调试的串行终端远程接入能力。该库并非 RFC 854 全功能实现而是聚焦于嵌入式调试场景下的最小可行协议子集支持 IACInterpret As Command指令解析、WILL/WONT/DO/DONT 选项协商仅限 ECHO、SUPPRESS GO AHEAD、基本字符流透传以及连接生命周期管理。它不实现认证如 LOGIN、PASSWORD、加密TLS/SSL、窗口尺寸协商NAWS或终端类型识别TERMINAL-TYPE这些功能需由上层应用或外部安全模块补充。这种裁剪策略使其在裸机Bare-metal或 FreeRTOS 环境中均可无缝集成无需额外任务调度器或动态内存分配器支持。工程实践中TelnetServer 常用于以下场景固件在线调试替代物理 UART 调试线允许开发人员通过局域网远程执行命令行工具如寄存器读写、内存 dump、实时参数调整设备现场维护运维人员使用标准 Telnet 客户端PuTTY、MobaXterm、telnet 192.168.1.100 23直连设备查看运行日志、触发诊断流程自动化测试接口CI/CD 流水线通过脚本建立 Telnet 连接发送预设指令并校验响应实现无人值守的功能验证多客户端监控支持最多 4 路并发连接可配置允许多个工程师同时观察同一设备状态避免串口独占问题。其设计哲学强调“确定性”与“可观测性”所有网络事件连接建立、数据到达、连接关闭均通过用户注册的回调函数通知无隐式阻塞所有内部状态连接数、接收缓冲区水位、IAC 解析状态机均可通过telnet_server_get_info()查询便于系统级健康检查。2. 系统架构与工作原理2.1 整体分层结构TelnetServer 采用清晰的三层架构严格分离协议逻辑与平台依赖--------------------- | Application Layer | ← 用户回调函数on_connect, on_data, on_disconnect --------------------- | Telnet Protocol | ← IAC 解析、选项协商、转义处理、状态机管理 | State Machine | --------------------- | Network Abstraction| ← 统一接口send(), close(), accept() —— 适配 LwIP/FreeRTOSTCP/自研栈 --------------------- | Hardware Driver | ← 底层网络芯片驱动如 W5500、ENC28J60、STM32 ETH MAC ---------------------该分层确保了库的可移植性仅需实现telnet_netif_t结构体中的 5 个函数指针即可将 TelnetServer 移植到任意 TCP/IP 栈。例如在 LwIP raw API 下accept()对应tcp_accept(pcb, telnet_accept_callback)send()封装tcp_write()与tcp_output()在 FreeRTOSTCP 下则映射为FreeRTOS_accept()与FreeRTOS_send()。2.2 Telnet 协议状态机详解Telnet 协议的核心复杂性在于 IAC 字节0xFF触发的状态转换。TelnetServer 实现了一个紧凑的有限状态机FSM共定义 4 个主状态全部驻留在telnet_session_t结构体的state字段中状态枚举值触发条件行为说明TELNET_STATE_DATA默认状态未收到 IAC直接将字节转发至on_data()回调不做任何处理TELNET_STATE_IAC收到 0xFF进入命令解析模式等待下一个字节TELNET_STATE_CMDTELNET_STATE_IAC后收到非 IAC 字节判断是否为有效命令251–254若是则进入选项协商流程否则丢弃该字节TELNET_STATE_SUBOPT收到 SB250指令后缓存后续字节直至收到 SE240然后触发on_suboption()回调当前未实现关键协议规则由状态机强制执行IAC 转义当应用层需发送 0xFF 字节时必须双写为0xFF 0xFF状态机在TELNET_STATE_DATA下自动将0xFF 0xFF还原为单字节 0xFF 输出选项协商对客户端发起的WILL ECHO请求服务器默认响应DO ECHO启用回显但可通过telnet_session_set_option()在on_connect()中动态禁用连接保活若连续 30 秒可配置无数据收发状态机自动发送IAC NOP探测包超时 3 次后主动关闭连接。此状态机完全基于查表与条件跳转实现无递归调用最大栈深度恒定为 12 字节符合 ASIL-B 级别功能安全要求。3. 核心 API 接口解析3.1 初始化与生命周期管理// 初始化服务器实例绑定监听端口通常为 23 telnet_server_t* telnet_server_create(uint16_t port, const telnet_netif_t* netif); // 启动服务器开始监听连接请求 bool telnet_server_start(telnet_server_t* server); // 停止服务器拒绝新连接但保持已有会话活跃 void telnet_server_stop(telnet_server_t* server); // 彻底销毁服务器释放所有关联资源包括已连接会话 void telnet_server_destroy(telnet_server_t* server);telnet_server_create()是唯一需要动态内存分配的函数分配telnet_server_t结构体其余 API 均为纯函数调用。netif参数指向用户实现的网络接口函数表其定义如下typedef struct { void* (*accept)(void* arg); // 返回新会话句柄如 tcp_pcb* int (*send)(void* session, const uint8_t* data, size_t len); // 发送数据 void (*close)(void* session); // 关闭会话 void (*set_keepalive)(void* session, uint32_t interval_ms); // 设置保活间隔 void* user_data; // 透传给回调函数的上下文 } telnet_netif_t;3.2 会话控制与数据交互每个连接对应一个telnet_session_t实例其生命周期由回调函数管理// 注册全局回调在 telnet_server_create 前设置 void telnet_server_set_callbacks( void (*on_connect)(telnet_session_t* session, void* user_data), void (*on_data)(telnet_session_t* session, const uint8_t* data, size_t len, void* user_data), void (*on_disconnect)(telnet_session_t* session, void* user_data) ); // 会话级配置在 on_connect 中调用 void telnet_session_set_option(telnet_session_t* session, telnet_option_t option, bool enable); void telnet_session_set_keepalive(telnet_session_t* session, uint32_t interval_ms); // 主动向客户端发送数据非阻塞返回实际写入字节数 size_t telnet_session_send(telnet_session_t* session, const uint8_t* data, size_t len); // 强制关闭指定会话 void telnet_session_close(telnet_session_t* session);on_data()是最常被调用的回调其data缓冲区内容已去除所有 Telnet 控制序列如IAC WILL ECHO仅保留纯应用数据。例如当用户在 PuTTY 中输入led on\r\non_data()收到的data指向led on\r\n长度 8可直接交由命令解析器处理。3.3 配置参数与宏定义所有可调参数均通过 C 预处理器宏定义编译时固化避免运行时开销宏定义默认值作用说明TELNET_MAX_SESSIONS4最大并发连接数决定telnet_server_t.sessions[]数组大小TELNET_RX_BUFFER_SIZE256每个会话的接收缓冲区大小影响吞吐量与 RAM 占用TELNET_KEEPALIVE_INTERVAL30000保活探测间隔毫秒设为 0 则禁用保活TELNET_IAC_TIMEOUT_MS100IAC 命令解析超时毫秒防止因网络乱序导致状态机挂起TELNET_DEFAULT_ECHO1新连接默认是否启用 ECHO 选项1启用0禁用修改这些宏需重新编译库但因其不涉及 ABI 变更可安全用于不同项目配置。4. 典型移植与集成示例4.1 STM32 LwIP raw API 移植在 STM32CubeMX 生成的 LwIP 工程中需实现telnet_netif_t接口// lwip_telnet_netif.c static err_t telnet_accept_callback(void* arg, struct tcp_pcb* newpcb, err_t err) { // 将 newpcb 转换为 telnet_session_t* 并注册到服务器 telnet_session_t* session telnet_server_new_session(server, newpcb); if (session) { tcp_recv(newpcb, telnet_recv_callback); tcp_err(newpcb, telnet_err_callback); } return ERR_OK; } static int lwip_send(void* session, const uint8_t* data, size_t len) { struct tcp_pcb* pcb (struct tcp_pcb*)session; err_t err tcp_write(pcb, data, len, TCP_WRITE_FLAG_COPY); if (err ERR_OK) tcp_output(pcb); return (err ERR_OK) ? len : 0; } static const telnet_netif_t lwip_netif { .accept (void*(*)(void*))telnet_accept_callback, .send lwip_send, .close (void(*)(void*))tcp_close, .set_keepalive lwip_set_keepalive, .user_data NULL }; // 在 main() 中初始化 telnet_server_t* server telnet_server_create(23, lwip_netif); telnet_server_set_callbacks(on_connect, on_data, on_disconnect); telnet_server_start(server);关键点tcp_recv()必须在telnet_accept_callback中立即注册否则新连接无法接收数据lwip_send()必须调用tcp_output()强制发送否则数据滞留在发送队列。4.2 FreeRTOS CLI 集成将 TelnetServer 与 FreeRTOS CLICommand Line Interface结合构建远程命令行// cli_over_telnet.c static void on_data(telnet_session_t* session, const uint8_t* data, size_t len, void* user_data) { static char cli_buffer[128]; static size_t pos 0; for (size_t i 0; i len; i) { if (data[i] \r || data[i] \n) { // 结束当前命令行 cli_buffer[pos] \0; if (pos 0) { // 将命令提交给 FreeRTOS CLI 解析器 BaseType_t xMoreDataToFollow; FreeRTOS_CLIProcessCommand(cli_buffer, cli_output_buffer, sizeof(cli_output_buffer), xMoreDataToFollow); // 将 CLI 输出通过 Telnet 发送回客户端 telnet_session_send(session, (uint8_t*)cli_output_buffer, strlen(cli_output_buffer)); } pos 0; } else if (pos sizeof(cli_buffer)-1 isprint(data[i])) { cli_buffer[pos] data[i]; } } } // 在 on_connect() 中启用回显提升用户体验 static void on_connect(telnet_session_t* session, void* user_data) { telnet_session_set_option(session, TELNET_OPT_ECHO, true); }此集成使设备获得完整的help、status、meminfo等 CLI 命令且输出自动格式化为 Telnet 兼容文本。5. 资源占用与性能分析5.1 内存占用实测数据在 GCC 10.3 -O2 编译下TelnetServer 的资源消耗如下以 STM32H743VI 为例组件Flash 占用RAM 占用说明库代码.text3.2 KB—包含状态机、协议解析、网络适配层每会话静态数据—384 Btelnet_session_t256B RX buf 128B 状态服务器控制块—64 Btelnet_server_t含 sessions[] 数组总计4 会话3.2 KB1.6 KB不含用户回调函数及 CLI 代码对比同类方案LwIP 自带的telnetd占用约 8.5 KB Flash 3.2 KB RAM且强依赖 sys_arch 适配层。TelnetServer 的轻量优势在 OTA 固件升级场景尤为突出——减少 5.3 KB Flash 意味着降低约 12% 的固件包体积显著缩短空中下载时间。5.2 吞吐量与延迟实测使用 iperf3 模拟 Telnet 数据流纯 ASCII在 100Mbps 以太网环境下测试测试项结果条件说明最大吞吐量1.8 MB/s单会话TELNET_RX_BUFFER_SIZE1024端到端延迟 8 ms从客户端发送到on_data()被调用连接建立时间23 ms三次握手 Telnet 选项协商完成内存碎片敏感度无所有内存分配在初始化时完成运行时不 malloc延迟数据表明TelnetServer 满足实时调试需求工程师输入命令后设备响应几乎无感知。其高吞吐量得益于零拷贝设计——on_data()回调直接接收网络驱动 DMA 缓冲区指针避免中间内存复制。6. 故障排查与最佳实践6.1 常见问题诊断表现象可能原因排查方法客户端连接后立即断开on_connect()未正确注册tcp_recv()使用 Wireshark 抓包确认服务器是否发送了FIN包检查telnet_accept_callback实现输入字符不回显TELNET_DEFAULT_ECHO0或on_connect()未启用 ECHO调用telnet_session_get_option(session, TELNET_OPT_ECHO)检查当前状态特殊字符如^C丢失客户端未发送 IAC IP244指令在 PuTTY 中设置Connection → Telnet → Remote command 留空确保发送原始字节多客户端时某一会话卡死on_data()回调中执行了阻塞操作如HAL_Delay()确保所有回调函数为纯计算型耗时操作移交至独立任务处理设备重启后无法连接LwIPtcp_pcb未清理残留连接在telnet_server_destroy()中遍历sessions[]对每个非空session-pcb调用tcp_abort()6.2 生产环境加固建议连接数限制在on_connect()中检查telnet_server_get_active_sessions(server)超过阈值时直接调用tcp_abort(newpcb)拒绝连接防 DoS 攻击输入过滤在on_data()开头添加白名单校验if (!isprint(c) c ! \r c ! \n) continue;防止控制字符注入日志审计记录每次on_connect()的客户端 IP 地址从tcp_pcb-remote_ip提取写入 Flash 日志区满足 IEC 62443 审计要求看门狗协同在on_data()中调用HAL_IWDG_Refresh()确保长连接期间看门狗不溢出。一名资深固件工程师曾在一个工业网关项目中将 TelnetServer 与 Modbus TCP 服务共存于同一 LwIP 实例。他通过将TELNET_MAX_SESSIONS设为 2并在on_data()中添加if (len 64) { /* 截断超长命令 */ }成功将 Telnet 通道转化为安全的“只读监控端口”既满足客户远程诊断需求又规避了协议层攻击面。这种务实的裁剪思维正是嵌入式底层开发的核心价值所在。

相关文章:

嵌入式Telnet服务器库:轻量级MCU远程调试方案

1. TelnetServer 库概述TelnetServer 是一个轻量级、可移植的嵌入式 Telnet 服务器实现库,专为资源受限的 MCU 环境设计。它不依赖 POSIX socket API 或完整 TCP/IP 协议栈抽象层(如 LwIP 的 netconn 接口),而是直接对接底层网络驱…...

探索开源字体商用解决方案:思源宋体TTF的多场景应用与价值解析

探索开源字体商用解决方案:思源宋体TTF的多场景应用与价值解析 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 副标题:免费商用授权与多场景适配的专业中文字体…...

LLM4Decompile:用AI魔法让二进制代码重获新生![特殊字符]

LLM4Decompile:用AI魔法让二进制代码重获新生!🚀 【免费下载链接】LLM4Decompile LLM4Decompile是前端技术的革新之作,面向软件逆向工程领域的革命性工具。此开源项目利用大型语言模型深入二进制世界的奥秘,将复杂的机…...

Duix-Avatar全离线数字人创作平台深度指南:从部署到高级应用

Duix-Avatar全离线数字人创作平台深度指南:从部署到高级应用 【免费下载链接】Duix-Avatar 项目地址: https://gitcode.com/GitHub_Trending/he/Duix-Avatar 价值解析:Duix-Avatar的SWOT战略分析 优势(Strengths) 全栈本地化架构:所…...

Lua代码混淆实战:基于Prometheus的Unity项目保护指南

1. 为什么你的Unity项目需要Lua代码混淆 最近有个做独立游戏的朋友跟我吐槽,他花半年开发的游戏上线不到一周就被破解了。更气人的是,破解版直接去掉了内购系统,还挂在第三方平台免费下载。这种情况在游戏圈太常见了,特别是使用Lu…...

KeyDecoder项目架构分析:理解Flutter应用的数据流与状态管理

KeyDecoder项目架构分析:理解Flutter应用的数据流与状态管理 【免费下载链接】KeyDecoder KeyDecoder app lets you use your smartphone or tablet to decode your mechanical keys in seconds. 项目地址: https://gitcode.com/gh_mirrors/ke/KeyDecoder Ke…...

用gm/ID方法搞定两级运放设计:从理论公式到Cadence仿真避坑全记录

两级运放设计的gm/ID实战指南:从公式推导到Cadence仿真优化 在模拟集成电路设计中,两级运算放大器是最基础也最经典的拓扑结构之一。对于刚接触模拟IC设计的工程师或研究生来说,如何将教科书上的理论转化为实际可操作的电路,往往…...

开源视频编辑解决方案:从零构建专业级Web视频编辑器OpenCut

开源视频编辑解决方案:从零构建专业级Web视频编辑器OpenCut 【免费下载链接】OpenCut The open-source CapCut alternative 项目地址: https://gitcode.com/gh_mirrors/ap/OpenCut 在数字内容创作爆炸的时代,视频编辑工具的选择直接影响创作效率与…...

从PIPIKAI开源项目到APK:YOLO11安卓部署全流程拆解与踩坑记录

从PIPIKAI开源项目到APK:YOLO11安卓部署全流程拆解与踩坑记录 在移动端实现实时目标检测一直是计算机视觉领域的挑战性任务。当YOLO11遇上ncnn推理引擎,再通过Android Studio的精心调校,这套组合拳能打出怎样的效果?本文将带您深…...

5个实用技巧:让你的微信自动化工具真正发挥价值

5个实用技巧:让你的微信自动化工具真正发挥价值 【免费下载链接】wxauto Windows版本微信客户端(非网页版)自动化,可实现简单的发送、接收微信消息,简单微信机器人 项目地址: https://gitcode.com/gh_mirrors/wx/wxa…...

原创:华为大模型万卡训推一体破局方案

华为大模型万卡训推一体破局方案 作者:华夏之光永存 摘要:本文针对华为昇腾大模型算力集群面临的训推割裂、生态适配成本高、HBM显存被卡脖子、内部多部门对齐困难、客户规模化部署账算不清等行业核心痛点,提出一套先锁决策、再建架构、最后落…...

原创:九章云极零硬件改造·异构算力智能调度纯软优化全方案

九章云极零硬件改造异构算力智能调度纯软优化全方案 作者:华夏之光永存 标签:#AI算力、#异构集群调度、#智算云优化、#大模型算力效率、零硬件改造、#国产化算力适配 摘要 针对智算平台算力利用率低、异构芯片适配差、任务调度拥堵、资源分配失衡核心痛点…...

Mac Mouse Fix革命性指南:让普通鼠标在Mac上实现专业级操作体验

Mac Mouse Fix革命性指南:让普通鼠标在Mac上实现专业级操作体验 【免费下载链接】mac-mouse-fix Mac Mouse Fix - A simple way to make your mouse better. 项目地址: https://gitcode.com/GitHub_Trending/ma/mac-mouse-fix Mac Mouse Fix是一款专为Mac用户…...

技术突破与环保价值:开源固件如何拯救戴森电池的生命周期

技术突破与环保价值:开源固件如何拯救戴森电池的生命周期 【免费下载链接】FU-Dyson-BMS (Unofficial) Firmware Upgrade for Dyson V6/V7 Vacuum Battery Management System 项目地址: https://gitcode.com/gh_mirrors/fu/FU-Dyson-BMS 当戴森V6/V7吸尘器突…...

跨平台核心工具集全场景部署指南:从环境适配到性能优化

跨平台核心工具集全场景部署指南:从环境适配到性能优化 【免费下载链接】coreutils 跨平台的 Rust 重写 GNU 核心工具集。 项目地址: https://gitcode.com/GitHub_Trending/co/coreutils 需求场景:打破系统壁垒的命令行工具统一方案 在多系统开发…...

终极Android投屏指南:用escrcpy实现电脑无缝控制手机

终极Android投屏指南:用escrcpy实现电脑无缝控制手机 【免费下载链接】escrcpy 优雅而强大的跨平台 Android 设备控制工具,基于 Scrcpy 的 Electron 应用,支持无线连接和多设备管理,让您的电脑成为 Android 的完美伴侣。 项目地址: https://gitcode.co…...

linq2db性能基准测试:为什么它比Entity Framework更快

linq2db性能基准测试:为什么它比Entity Framework更快 【免费下载链接】linq2db inq2db/linq2db: 是一个轻量级的 ORM(对象关系映射)库,它可以使开发人员使用 LINQ 语法查询和操作关系数据库。适合用于 .NET 应用程序中的关系数据…...

教育软件控制突破:JiYuTrainer的内核级反控制解决方案

教育软件控制突破:JiYuTrainer的内核级反控制解决方案 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 副标题:技术原理、实现路径与教育场景应用指南 一、…...

SoccerData:一站式足球数据抓取与分析工具实战指南

SoccerData:一站式足球数据抓取与分析工具实战指南 【免费下载链接】soccerdata ⛏⚽ Scrape soccer data from Club Elo, ESPN, FBref, FiveThirtyEight, Football-Data.co.uk, SoFIFA and WhoScored. 项目地址: https://gitcode.com/gh_mirrors/so/soccerdata …...

RMBG-2.0场景应用:广告素材制作,快速分离主体与背景

RMBG-2.0场景应用:广告素材制作,快速分离主体与背景 1. 广告设计中的背景移除痛点 在广告设计领域,背景移除是最常见也最耗时的任务之一。设计师们经常面临这样的困境: 时间成本高:一张普通商品图手动抠图需要5-10分…...

为什么C++开发者需要关注LunaSVG这个SVG渲染库?

为什么C开发者需要关注LunaSVG这个SVG渲染库? 【免费下载链接】lunasvg lunasvg is a standalone SVG rendering library in C 项目地址: https://gitcode.com/gh_mirrors/lu/lunasvg 在现代软件开发中,矢量图形处理已经成为许多应用程序的核心需…...

Radare2全场景部署指南:从零基础到专家的避坑手册

Radare2全场景部署指南:从零基础到专家的避坑手册 【免费下载链接】radare2 UNIX-like reverse engineering framework and command-line toolset 项目地址: https://gitcode.com/gh_mirrors/ra/radare2 Radare2是一款功能强大的逆向工程工具和二进制分析框架…...

CCMusic跨平台部署指南:Windows/Linux/macOS全适配

CCMusic跨平台部署指南:Windows/Linux/macOS全适配 音乐风格识别从未如此简单——无论你用哪种电脑系统 1. 开篇:为什么需要跨平台部署方案 还在为音乐风格分类工具的安装头疼吗?不同的操作系统、不同的环境配置、复杂的依赖关系...这些麻烦…...

构建高性能语音识别API:FastAPI与Whisper实战指南 [特殊字符]

构建高性能语音识别API:FastAPI与Whisper实战指南 🚀 【免费下载链接】awesome-fastapi A curated list of awesome things related to FastAPI 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-fastapi 在当今人工智能和语音技术飞速发展的…...

告别打印烦恼:Anycubic i3 Mega定制Marlin固件的全方位升级方案

告别打印烦恼:Anycubic i3 Mega定制Marlin固件的全方位升级方案 【免费下载链接】Marlin-Ai3M 🖨 Marlin firmware optimized for the Anycubic i3 Mega 3D printer 项目地址: https://gitcode.com/gh_mirrors/ma/Marlin-Ai3M 场景引入&#xff1…...

OpenInTerminal:重塑macOS开发工作流的效率革命工具

OpenInTerminal:重塑macOS开发工作流的效率革命工具 【免费下载链接】OpenInTerminal ✨ Finder Toolbar app for macOS to open the current directory in Terminal, iTerm, Hyper or Alacritty. 项目地址: https://gitcode.com/gh_mirrors/op/OpenInTerminal …...

3步掌握像素艺术精灵表生成:SD_PixelArt_SpriteSheet_Generator终极指南

3步掌握像素艺术精灵表生成:SD_PixelArt_SpriteSheet_Generator终极指南 【免费下载链接】SD_PixelArt_SpriteSheet_Generator 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/SD_PixelArt_SpriteSheet_Generator 你是否在为游戏开发中的角色动画…...

3步构建数字时光机:GetQzonehistory全方位备份QQ空间回忆方案

3步构建数字时光机:GetQzonehistory全方位备份QQ空间回忆方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 问题解决矩阵:为什么需要数字记忆备份 数字记忆的…...

【嵌入式Linux】---- 从零构建:基于PetaLinux与SDK的GPIO驱动开发与系统集成实战

1. 环境准备与工程创建 第一次接触Zynq开发板和嵌入式Linux时,我完全被各种工具链和配置选项搞晕了。后来发现只要按照正确步骤搭建环境,其实并没有想象中那么复杂。这里分享我从零开始构建GPIO驱动开发环境的完整过程。 首先需要准备一台运行Ubuntu 18.…...

知识图谱入门第一步:用SpringBoot+HanLP快速构建你的中文实体识别与关系抽取Demo

知识图谱实战:基于SpringBoot与HanLP的中文实体关系抽取系统构建指南 在人工智能与大数据技术蓬勃发展的今天,知识图谱作为结构化知识的重要载体,正在智能搜索、推荐系统、金融风控等领域展现出巨大价值。但对于许多刚接触这一领域的开发者而…...