libwebsockets 极简 HTTP 服务器示例:一个程序灵活切换 libuv / libev / libevent 等事件循环后端
后端网络通信【免费下载链接】libwebsocketscanonical libwebsockets.org networking library项目地址https://gitcode.com/gh_mirrors/li/libwebsockets点击查看免费下载导读lws-minimal-http-server-eventlib是 libwebsockets 仓库中一个极具代表性的最小可用 HTTP 服务器示例它用一份不足 150 行的 C 源码演示了如何让同一个服务器程序在libuv、libevent、libev、glib以及 lws 默认的poll()事件循环后端之间自由切换且不需要改动任何业务代码。本文以该示例为骨架完整讲解它的命令行参数、构建运行方式、上下文context与挂载mount配置并结合仓库源码剖析事件循环后端的运行时选择机制与 evlib 插件架构帮助你快速上手把 lws 接入自己应用已有的事件循环。示例定位一份演示事件库无关的极简服务器该示例位于仓库的 minimal-examples-lowlevel/http-server/minimal-http-server-eventlib/ 目录核心源码为 minimal-http-server-eventlib.c源码头部注释明确指出This demonstrates a minimal http[s] server that can work with any of the supported event loop backends, or the default poll() one。它的设计意图非常清晰服务器逻辑HTTP 挂载、静态文件服务、404 处理与事件循环后端的选择完全解耦通过info-options中的标志位在运行时决定使用哪个事件库未显式指定时回落到 lws 内置的、基于poll()的默认事件循环行为与普通的 lws 服务器完全一致。在动手之前建议先阅读仓库中的 READMEs/README.event-loops-intro.md事件循环设计考量与 READMEs/README.event-libs.mdlws 事件库支持综述它们是理解本示例背后设计哲学的官方配套文档。命令行参数总览原文档给出了本示例支持的命令行开关结合源码 minimal-http-server-eventlib.c 中switches[]表的完整定义实际可用的参数如下命令行选项含义说明-d loglevel调试日志详细程度十进制如-d 15数值越大输出越详细--port port监听端口默认7681源码会校验取值必须在 165535 的 16 位范围内非法值直接报错退出--uv使用 libuv 事件库要求 lws 以-DLWS_WITH_LIBUV1配置编译--event使用 libevent 事件库要求 lws 以-DLWS_WITH_LIBEVENT1配置编译--ev使用 libev 事件库要求 lws 以-DLWS_WITH_LIBEV1配置编译--glib使用 glib 事件库要求 lws 以-DLWS_WITH_GLIB1配置编译源码支持README 表格中未列出-s启用 TLS / https使用随示例分发的localhost-100y.cert与localhost-100y.key仅在 lws 以 TLS 支持编译时生效源码用#if defined(LWS_WITH_TLS)包裹--help打印帮助信息由lws_switches_print_help()自动生成其中事件库参数具有优先级关系源码中通过if / else if链依次检查--uv→--event→--ev→--glib因此如果同时传入多个事件库参数只有优先级最高最先被检查的那个生效当四个事件库参数都未出现时程序注册标准的SIGINT处理并运行默认 poll 循环。构建与运行原文档给出了最简构建方式在示例目录内执行$ cmake . make对应目录下的 CMakeLists.txt 通过find_package(libwebsockets CONFIG REQUIRED)找到已安装的 lws并用require_lws_config()强制要求两项编译期能力LWS_ROLE_H1HTTP/1 角色即提供 HTTP 服务的底层协议支持LWS_WITH_SERVER服务端能力。只有这两个条件满足时才会生成可执行文件lws-minimal-http-server-eventlib并链接websockets_shared或静态版websockets。也就是说lws 本体必须已经用 CMake 安装到系统中并且开启了LWS_ROLE_H1与LWS_WITH_SERVER而事件库libuv 等则按需以-DLWS_WITH_LIBUV1、-DLWS_WITH_LIBEVENT1、-DLWS_WITH_LIBEV1、-DLWS_WITH_GLIB1配置。不带任何参数直接启动默认 poll 循环 默认端口 7681$ ./lws-minimal-http-server-eventlib [2018/03/04 09:30:02:7986] USER: LWS minimal http server-eventlib | visit http://localhost:7681 [2018/03/04 09:30:02:7986] NOTICE: Creating Vhost default port 7681, 1 protocols, IPv6 on然后访问 http://localhost:7681 即可看到示例页面。常见运行变体$ ./lws-minimal-http-server-eventlib --uv # 使用 libuv 事件循环 $ ./lws-minimal-http-server-eventlib --event -d15 # 使用 libevent并输出详细日志 $ ./lws-minimal-http-server-eventlib --port 8080 # 换端口默认 poll 循环 $ ./lws-minimal-http-server-eventlib -s # 以 TLS 模式启动 https://localhost:7681启动日志中的Creating Vhost default port 7681, 1 protocols, IPv6 on表明 vhost 已创建、IPv6 默认开启这是确认服务正常就绪的典型信号。源码拆解一个 HTTP 服务器是如何搭起来的静态文件挂载mount服务器要服务的静态内容通过struct lws_http_mount声明见 minimal-http-server-eventlib.cstatic const struct lws_http_mount mount { .mountpoint /, /* mountpoint URL */ .origin ./mount-origin, /* serve from dir */ .def index.html, /* default filename */ .origin_protocol LWSMPRO_FILE, /* files in a dir */ .mountpoint_len 1, /* char count */ };对照头文件 lws-context-vhost.h 中struct lws_http_mount的定义各字段含义如下mountpointURL 命名空间中的挂载点/表示挂在站点根路径origin对应文件系统中的目录示例固定为启动目录下的./mount-origin其中的 index.html、404.html 以及 libwebsockets.org-logo.svg 等资源都会通过它对外提供def目录的默认首页文件名origin_protocol挂载协议类型LWSMPRO_FILE值为 2见 lws-context-vhost.h表示从文件系统目录直接提供服务同一枚举还包含 HTTP/HTTPS 反向代理LWSMPRO_HTTP/LWSMPRO_HTTPS、CGILWSMPRO_CGI、URL 重定向LWSMPRO_REDIR_HTTP/LWSMPRO_REDIR_HTTPS等其他挂载方式mountpoint_lenmountpoint字符串的字符长度必须显式给出。若想改服务目录只需修改mount.origin例如换成绝对路径/var/www/html。上下文context创建与默认配置main()中依次完成初始化默认配置lws_context_info_defaults(info, NULL)填充struct lws_context_creation_info的默认值服务端 fd 表大小info.fd_limit_per_thread 0注释说明作为服务器将 fd 表放大到进程限制即不预设上限处理内置命令行选项lws_cmdline_option_handle_builtin(argc, argv, info)统一解析-d、--port等标准选项相关 API 声明见 lws-misc.h端口处理默认 7681--port传入后经atoi()解析并校验 165535 范围非法则打印Port %d is outside valid 16-bit range并退出挂载与 404info.mounts mount绑定静态文件挂载info.error_document_404 /404.html指定当请求的文件不存在时改而提供该 URL 路径对应头文件 lws-context-vhost.h 中.error_document_404字段的语义示例首页里专门放了一个指向不存在页面notextant.html的链接用于直观验证 404 处理器安全响应头info.options置位LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE位 28。按 lws-context-vhost.h 的注释这会为每个 HTTP 响应附带一套非常严格、符合 Mozilla Observatory 建议的默认安全头例如严格 CSP页面自带的 strict-csp.svg 即用于在浏览器中展示该 CSP 生效后的效果。若你的页面需要放宽策略如加载站外图片或内联脚本官方建议改用info.headers自行定制响应头信号回调info.signal_cb signal_cb与info.pcontext context让 lws 在收到SIGTERM/SIGINT时统一回调signal_cb()并执行lws_context_destroy(context)完成优雅退出默认poll路径下则直接注册sigint_handler。事件库的运行时选择事件库的选择完全发生在上下文创建阶段核心代码如下见 minimal-http-server-eventlib.cif (lws_cmdline_option(argc, argv, switches[LWS_SW_UV].sw)) info.options | LWS_SERVER_OPTION_LIBUV; else if (lws_cmdline_option(argc, argv, switches[LWS_SW_EVENT].sw)) info.options | LWS_SERVER_OPTION_LIBEVENT; else if (lws_cmdline_option(argc, argv, switches[LWS_SW_EV].sw)) info.options | LWS_SERVER_OPTION_LIBEV; else if (lws_cmdline_option(argc, argv, switches[LWS_SW_GLIB].sw)) info.options | LWS_SERVER_OPTION_GLIB; else signal(SIGINT, sigint_handler);对应的选项标志在 lws-context-vhost.h 中均有定义与注释标志位含义LWS_SERVER_OPTION_LIBEV14(CTX) 使用 libev 事件循环LWS_SERVER_OPTION_LIBUV110(CTX) 使用 libuv 事件循环LWS_SERVER_OPTION_LIBEVENT121(CTX) 使用 libevent 事件循环LWS_SERVER_OPTION_GLIB133(CTX) 使用 glib 事件循环LWS_SERVER_OPTION_SDEVENT137(CTX) 使用 sd-event 事件循环LWS_SERVER_OPTION_ULOOP138(CTX) 使用 libubox / uloop 事件循环值得一提示例 README 只宣传了--uv/--event/--ev三个开关但源码还额外支持--glib以及 enum 中预留的 sdevent、uloop 后端。这些未宣传的开关同样可用只是要求 lws 在编译时开启了对应的事件库支持。此外事件循环的服务循环入口也随之改变示例主体是while (!lws_service(context, 0));。按 lws-service.h 的语义lws_service()在默认 poll 循环与事件库内部循环下的行为略有差异——后者当销毁流程启动例如lws_default_loop_exit()或信号处理触发后返回-1此时lws_context_destroy()负责收尾完成销毁。事件库后端的底层机制ops 抽象与 evlib 插件lws_event_loop_ops统一的事件循环接口lws 之所以能一份代码、多后端运行根源在于它在 lws-eventlib-exports.h 中定义了一个事件循环操作表struct lws_event_loop_ops包括上下文初始化init_context、vhost 监听 wsi 初始化init_vhost_listen_wsi、每线程循环启动init_pt/run_pt、wsi 的读写事件控制io、接收连接sock_accept等一整套钩子。每个事件库libuv、libev、libevent、glib、sdevent、uloop 以及默认 poll都实现了一份自己的 ops 表lws 核心在创建 context 时根据info.options里的标志位选择对应实现。以 libev 为例libev.c 中可以看到典型的桥接代码lws_accept_cb()把 libev 的ev_io回调事件翻译成LWS_POLLIN/LWS_POLLOUT并转发给lws_service_fd_tsi()而lws_ev_hrtimer_cb()/lws_ev_idle_cb()负责把 lws 的定时器调度sulscheduled us list与强制服务请求接到 libev 的ev_timer/ev_idle上。libuv 侧对应的是 libuv.c 中的uv_timer_t、uv_idle_t、uv_poll_t回调。也就是说wsi 的读写事件、lws 内部定时器、服务强制唤醒这三件事在每个后端下都有对应的原生实现。v4.1 之后的 evlib 插件机制按仓库 READMEs/README.event-libs.md 的说明v4.0 及以前事件库支持直接编译进 libwebsockets 库本体用户代码在运行时用info-options标志选择即可唯一的限制是libev 与 libevent 不能同时编译因为两者的头文件命名空间冲突v4.1 及以后引入新的 CMake 选项LWS_WITH_EVLIB_PLUGINS。在 UNIX 平台默认开启值为 1此时每个启用的事件库支持被独立编译成动态插件lws 在运行时看到info-options中请求的标志后才按需加载对应的插件。这带来了两个好处其一libev 与 libevent 可以同时存在各自隔离在独立插件中lws 核心库构建时完全不引入它们的头文件其二发行版打包时可以按插件拆包应用只依赖自己需要的那个事件库插件包。插件产物命名安装于 lws 库所在目录Linux 上通常为/usr/local/lib/事件库插件文件名gliblibwebsockets-evlib_glib.solibeventlibwebsockets-evlib_event.solibuvlibwebsockets-evlib_uv.solibevlibwebsockets-evlib_ev.so插件化构建逻辑由 lib/event-libs/CMakeLists.txt 中的create_evlib_plugin()宏实现每个插件是一个SHARED库目标链接到websockets_shared与对应事件库并按组件COMPONENT分别安装而 poll 支持则始终编译进库本体作为默认后端。CMake 辅助配置LWS_WITH_DISTRO_RECOMMENDED也已适配为启用事件库插件支持的推荐组合。需要说明的是示例中的--uv等开关在两种构建方式下都能工作——插件化只是改变了事件库代码的打包与加载方式info-options的运行时选择语义保持不变。事件循环的正确使用姿势结合仓库 READMEs/README.event-loops-intro.md 与示例可以把使用要点归纳如下单线程模型事件循环要求所有事情在一个线程内按序完成因此不需要锁也天然规避了锁序、竞态等线程 bug但反过来lws 的 API 除lws_cancel_service()外都不能从事件循环线程以外的线程调用事件循环本身非线程安全非阻塞 IO循环只在被通知可读/可写时才执行 IO不再为阻塞读写专门分配线程空闲时事件循环停留在等待中占用 0% CPU外部循环接入如果应用自己持有 libuv/libevent 等事件循环所谓 foreign loop可以在info.foreign_loops中传入lws 以客人身份运行在其上可干净地创建与销毁 context 而不干扰循环本身多代码库协同让不同库共享同一事件循环是首选方案README.event-loops-intro.md 将其列为最优选项其次是使用 lws 的 RAW wsi 语义、自定义 evlib shim最后才是跨线程协作——把其他线程要执行的工作通过共享内存排队后用lws_cancel_service()唤醒事件循环线程优雅退出示例通过info.signal_cb在信号到来时调用lws_context_destroy()事件库路径下这会在循环内部启动销毁流程使lws_service()返回-1随后示例代码退出while循环并调用最终的lws_context_destroy(context)完成清理对应 lws-service.h 的返回值约定。验证清单与进阶方向启动示例后可以按下面的清单快速验证各功能点默认循环可用直接运行浏览器打开http://localhost:7681应看到示例页含 lws logo 与严格 CSP 图示404 处理点击首页中的notextant.html链接或直接访问该路径应返回 404.html 定义的页面验证info.error_document_404生效事件库切换分别用--uv、--event、--ev、--glib启动并再次访问功能表现应完全一致这正是后端无关的验证方式TLS 模式-s启动后访问https://localhost:7681示例自带 100 年有效期的自签证书 localhost-100y.cert / localhost-100y.key日志级别-d15观察更详细的调试输出--port 0之类的非法端口会被范围校验拒绝。更进一步若想把这个示例改造成自己的服务器骨架可关注替换mount.origin指向真实站点目录、通过info.headers自定义响应头以放宽 CSP、把事件库换成 sdevent/uloop需 lws 开启对应编译选项、以及把 lws 接入应用自有的 foreign loopinfo.foreign_loops。仓库中 minimal-examples-lowlevel/http-server/ 目录还提供了一批同族示例如自定义事件循环 shim 的minimal-http-server-eventlib-custom风格用法可以对照阅读加深对事件循环接入点的理解。赞分享后端网络通信【免费下载链接】libwebsocketscanonical libwebsockets.org networking library项目地址https://gitcode.com/gh_mirrors/li/libwebsockets点击查看免费下载相关推荐libwebsockets 最小 HTTP 服务器事件循环后端示例libuv / libev / libevent 一键切换实战解析libwebsockets 最小 HTTP 服务器事件循环后端示例libuv / libev / libevent 一键切换实战解析 libwebsocket人工智能AI Agent多模态语音AI 应用libwebsockets事件循环集成终极指南libuv、libevent、libev完整配置教程libwebsockets事件循环集成终极指南libuv、libevent、libev完整配置教程 libwebsockets是一个功能强大的轻量级C网络库后端网络通信libwebsockets 多线程 WebSocket 服务器实战foreign libuv 事件循环与 SMP 组合示例剖析libwebsockets 多线程 WebSocket 服务器实战foreign libuv 事件循环与 SMP 组合示例剖析 libwebsocketsl人工智能AI Agent多模态语音AI 应用上一篇告别烦恼Mac上制作Windows启动盘的最佳解决方案下一篇ClickHouse 测试数据集一键构建create-test-datasets 技能与 hits/visits/TPC-DS/TPC-H 数据集详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

如何快速跑通 MaterializeYourApp:老 Android 项目构建避坑指南(jcenter弃用解决方案)

如何快速跑通 MaterializeYourApp:老 Android 项目构建避坑指南(jcenter弃用解决方案)

【免费下载链接】MaterializeYourApp Example of a Material App for Android 项目地址: https://gitcode.com/gh_mirrors/ma/MaterializeYourApp 点击查看 免费下载 MaterializeYourApp 是一个经典的 Android Material Design 示例应用,完整演示了 Nav…

2026/10/14 1:52:15 阅读更多 →
软件开发项目履约保证金的风险与应对策略

软件开发项目履约保证金的风险与应对策略

1. 项目背景与行业现状在软件开发行业,履约保证金已经成为许多项目招标过程中的标配要求。最近接洽的一个企业级ERP系统开发项目,甲方明确要求参与竞标的开发团队需缴纳合同金额20%的履约保证金。这让我不得不重新审视这个行业普遍存在却鲜少被深入讨论的…

2026/10/14 1:51:15 阅读更多 →
Ponytail技术解析:从3D角色头发物理模拟到工程实践

Ponytail技术解析:从3D角色头发物理模拟到工程实践

我无法根据当前输入生成符合要求的博文。原因如下:项目标题“ponytail”本身是一个常见英文单词,意为“马尾辫”,属于日常服饰/造型/美妆/时尚领域术语;但项目正文为空、关键词为空、摘要描述为空;所谓“相关热搜词”与…

2026/10/14 1:51:15 阅读更多 →

最新新闻

Flutter scratch_space鸿蒙适配实战与性能优化

Flutter scratch_space鸿蒙适配实战与性能优化

1. 项目背景与核心价值在跨平台开发领域,Flutter因其高效的渲染性能和丰富的生态体系已成为移动端开发的主流选择之一。而scratch_space作为Flutter生态中专注于临时构建空间管理的三方库,在资源隔离和任务协同方面表现出色。但随着鸿蒙系统的崛起&#…

2026/10/14 2:37:27 阅读更多 →
Java 企业级工具类全家桶-83-RSA非对称加解密与签名工具类

Java 企业级工具类全家桶-83-RSA非对称加解密与签名工具类

📋 目录 一、工具类功能二、所需环境三、方法与调用示例(按需调用)四、工具类源码(可直接复制) 一、工具类功能 公钥加密私钥解密、私钥签名公钥验签,加密固定 RSA-OAEP(SHA-256&#xff0c…

2026/10/14 2:37:27 阅读更多 →
Java 企业级工具类全家桶-43-List转Map工具类

Java 企业级工具类全家桶-43-List转Map工具类

📋 目录 一、工具类功能二、所需环境三、方法与调用示例(按需调用)四、工具类源码(可直接复制) 一、工具类功能 一次遍历把集合摊成 Map,按键分组、按键分组并只抽取某个属性、一个键只对应一个值三种形…

2026/10/14 2:37:27 阅读更多 →
基于 STM32 的智能拐杖设计与 Proteus 仿真+源码

基于 STM32 的智能拐杖设计与 Proteus 仿真+源码

基于 STM32 的智能拐杖设计与 Proteus 仿真实现摘要我国视力障碍人群数量庞大,老龄化进程加速又使老年出行安全问题日益突出。传统盲杖功能单一,仅能提供触地探路的机械辅助,无法感知前方悬空障碍、积水坑洼与远距离障碍物,更缺乏…

2026/10/14 2:37:27 阅读更多 →
SUMO TraCI函数调用深度解析:从轮询到订阅的性能优化实战

SUMO TraCI函数调用深度解析:从轮询到订阅的性能优化实战

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

2026/10/14 2:37:27 阅读更多 →
LLM_端到端自动驾驶

LLM_端到端自动驾驶

EAI:Embodied Artificial Intelligent,E2E:End to End,LLM:Large Language Mode 端到端自动驾驶专题:多模态输入融合、开源框架、头部企业与性能对比核心定义:端到端自动驾驶分为两类 纯端到端&…

2026/10/14 2:36:26 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →