ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WSL WslcSDK 端口映射 API 详解:WslcSetContainerSettingsPortMappings 使用指南

WSL WslcSDK 端口映射 API 详解:WslcSetContainerSettingsPortMappings 使用指南 WSL WslcSDK 端口映射 API 详解WslcSetContainerSettingsPortMappings 使用指南【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWSLWindows Subsystem for Linux的 WslcSDK 提供了一套用于管理 WSL 容器的 C API其中WslcSetContainerSettingsPortMappings负责在容器创建前设置宿主机与容器之间的端口映射规则是搭建Windows 宿主机 ⇄ WSL 容器网络服务暴露链路的关键接口。本文将基于官方 API 参考文档与仓库源码、测试用例完整讲解该函数的签名、参数语义、底层校验逻辑、完整调用流程与当前实现的限制帮助你正确地将容器内服务映射到 Windows 宿主机的指定端口与地址。1. API 概览WslcSetContainerSettingsPortMappings是 WslcSDK 中一组 OPTIONAL CONTAINER SETTINGS可选容器设置API 之一用于为尚未创建的容器批量写入端口映射配置。完整声明定义在头文件 src/windows/WslcSDK/wslcsdk.h#L257-L260 中同时作为导出符号列于 src/windows/WslcSDK/wslcsdk.defSTDAPI WslcSetContainerSettingsPortMappings( _In_ WslcContainerSettings* containerSettings, _In_reads_opt_(portMappingCount) const WslcContainerPortMapping* portMappings, _In_ uint32_t portMappingCount);参数说明参数类型方向含义containerSettingsWslcContainerSettings*in由 WslcInitContainerSettings 初始化得到的容器设置句柄不透明结构portMappingsconst WslcContainerPortMapping*in, optional指向端口映射数组的指针可为NULL用于清空映射portMappingCountuint32_tin端口映射条目的数量返回值类型为HRESULT。S_OK表示设置成功参数非法时返回E_INVALIDARG暂不支持的协议返回E_NOTIMPL详见下文源码级实现剖析。该 API 只是把映射写入容器设置对象真正的端口监听与转发发生在 WslcCreateContainer / WslcStartContainer 之后——即端口映射属于创建期配置必须在创建容器之前完成设置。2. 前置知识映射结构与协议枚举WslcSetContainerSettingsPortMappings的输入数组元素类型为WslcContainerPortMapping完整定义见 doc/docs/api-reference/c/structures/wslccontainerportmapping.mdtypedef struct WslcContainerPortMapping { _In_ uint16_t windowsPort; // Port on Windows host _In_ uint16_t containerPort; // Port inside container _In_ WslcPortProtocol protocol; // TCP or UDP // if you want to override the default binding address _In_opt_ struct sockaddr_storage* windowsAddress; // accepts ipv4/6 } WslcContainerPortMapping;字段类型说明windowsPortuint16_tWindows 宿主机上对外监听的端口containerPortuint16_t容器内部服务的端口protocolWslcPortProtocol传输协议TCP 或 UDPwindowsAddressstruct sockaddr_storage*可选覆盖宿主机默认绑定地址支持 IPv4/IPv6其中protocol字段使用枚举 WslcPortProtocoltypedef enum WslcPortProtocol { WSLC_PORT_PROTOCOL_TCP 0, WSLC_PORT_PROTOCOL_UDP 1 } WslcPortProtocol;枚举值数值说明WSLC_PORT_PROTOCOL_TCP0TCP 协议当前唯一受支持的值WSLC_PORT_PROTOCOL_UDP1UDP 协议当前仓库实现中返回E_NOTIMPLcontainerSettings本身是不透明结构见 doc/docs/api-reference/c/structures/wslccontainersettings.md以对齐字节数组形式隐藏内部布局调用方只能通过WslcInitContainerSettings初始化和一系列WslcSetContainerSettings*函数来填充。这正是 WslcSDK 的设计模式先初始化、再逐项设置、最后创建容器。3. 基础使用示例将容器 80 端口映射到宿主机 8080官方 API 参考文档wslcsetcontainersettingsportmappings.md给出了最核心的单条映射示例完整继承如下WslcContainerPortMapping portMappings[1] { 0 }; portMappings[0].windowsPort (uint16_t)8080; portMappings[0].containerPort (uint16_t)80; portMappings[0].protocol WSLC_PORT_PROTOCOL_TCP; portMappings[0].windowsAddress NULL; HRESULT hr WslcSetContainerSettingsPortMappings( containerSettings, portMappings, (uint32_t)_countof(portMappings));这段代码的语义是将 Windows 宿主机的 8080 端口默认绑定地址转发到容器内的 80 端口走 TCP 协议。windowsAddress NULL表示使用默认绑定地址不覆盖宿主机的监听地址。将其放入完整生命周期中一个最小可运行的调用序列为// 1. 初始化容器设置 WslcContainerSettings containerSettings; HRESULT hr WslcInitContainerSettings(python:3.12-alpine, containerSettings); if (FAILED(hr)) { /* 处理错误 */ } // 2. 可选设置容器名称、网络模式等 hr WslcSetContainerSettingsName(containerSettings, my-web-container); hr WslcSetContainerSettingsNetworkingMode(containerSettings, WSLC_CONTAINER_NETWORKING_MODE_BRIDGED); // 3. 设置端口映射 WslcContainerPortMapping portMappings[1] { 0 }; portMappings[0].windowsPort (uint16_t)8080; portMappings[0].containerPort (uint16_t)80; portMappings[0].protocol WSLC_PORT_PROTOCOL_TCP; portMappings[0].windowsAddress NULL; hr WslcSetContainerSettingsPortMappings(containerSettings, portMappings, (uint32_t)_countof(portMappings)); if (FAILED(hr)) { /* 处理错误 */ } // 4. 创建并启动容器此时端口映射才会真正生效 // WslcContainer container nullptr; // hr WslcCreateContainer(session, containerSettings, container, nullptr); // hr WslcStartContainer(container, WSLC_CONTAINER_START_FLAG_ATTACH, nullptr);注意从源码测试可以看出若网络模式为WSLC_CONTAINER_NETWORKING_MODE_NONE时仍设置端口映射WslcCreateContainer会返回E_INVALIDARG见下文边界行为与错误处理因此配置端口映射时务必搭配支持端口转发的网络模式如WSLC_CONTAINER_NETWORKING_MODE_BRIDGED。4. 绑定地址覆盖IPv4 与 IPv6当需要把宿主机监听限制到特定地址而不是全部网卡时通过windowsAddress字段传入struct sockaddr_storage*。参考 test/windows/WslcSdkTests.cpp#L916-L996 中的两个功能测试可以写出标准的 IPv4 绑定写法sockaddr_storage addr4{}; auto* sin4 reinterpret_castsockaddr_in*(addr4); sin4-sin_family AF_INET; inet_pton(AF_INET, 127.0.0.1, sin4-sin_addr); WslcContainerPortMapping mapping{}; mapping.windowsPort 12343; mapping.containerPort 8000; mapping.protocol WSLC_PORT_PROTOCOL_TCP; mapping.windowsAddress addr4; hr WslcSetContainerSettingsPortMappings(containerSettings, mapping, 1);IPv6 绑定如仅允许回环地址::1访问写法相同只需把地址族切换为AF_INET6sockaddr_storage addr6{}; auto* sin6 reinterpret_castsockaddr_in6*(addr6); sin6-sin6_family AF_INET6; inet_pton(AF_INET6, ::1, sin6-sin6_addr); WslcContainerPortMapping mapping{}; mapping.windowsPort 12344; mapping.containerPort 8000; mapping.protocol WSLC_PORT_PROTOCOL_TCP; mapping.windowsAddress addr6; hr WslcSetContainerSettingsPortMappings(containerSettings, mapping, 1);5. 源码级实现剖析参数校验与内部存储WslcSetContainerSettingsPortMappings的实现位于 src/windows/WslcSDK/wslcsdk.cpp#L1041-L1064逻辑非常清晰可以归纳为三步。第一步取值并做空指针/计数一致性校验。auto internalType CheckAndGetInternalType(containerSettings); RETURN_HR_IF(E_INVALIDARG, (portMappings nullptr portMappingCount ! 0) || (portMappings ! nullptr portMappingCount 0));即portMappings与portMappingCount必须同生共死指针为空且数量非零、或指针非空且数量为零都会立即返回E_INVALIDARG。这与测试 test/windows/WslcSdkTests.cpp#L841-L854 中两个负面用例一一对应。第二步逐条校验每条映射的地址族与协议。for (uint32_t i 0; i portMappingCount; i) { if (portMappings[i].windowsAddress ! nullptr) { const auto family portMappings[i].windowsAddress-ss_family; RETURN_HR_IF_MSG( E_INVALIDARG, family ! AF_INET family ! AF_INET6, Unsupported address family: %d at port mapping index %u, family, i); } RETURN_HR_IF_MSG( E_NOTIMPL, portMappings[i].protocol ! 0, Unsupported protocol: %d at port mapping index %u, portMappings[i].protocol, i); }地址族限制windowsAddress只接受AF_INETIPv4与AF_INET6IPv6其他地址族如AF_UNIX一律返回E_INVALIDARG错误消息会带出具体的地址族编号与数组下标便于定位出错条目。测试 test/windows/WslcSdkTests.cpp#L998-L1013 用AF_UNIX验证了这条路径。协议限制目前实现只接受WSLC_PORT_PROTOCOL_TCP枚举值为 0传入 UDP枚举值为 1会返回E_NOTIMPL。这一限制也被记录在 doc/docs/api-reference/c/not-yet-implemented-apis.md 中属于已声明但尚未实现的能力清单——即当前仓库中端口映射仅支持 TCP。第三步将映射数组及数量写入内部类型并返回S_OK。internalType-ports portMappings; internalType-portsCount portMappingCount; return S_OK;注意ports保存的是调用方传入的指针因此调用方必须在容器真正创建之前保持该数组内存有效这与整个 WslcSDK 设置对象即描述符 的设计一致。6. 边界行为与错误处理综合源码实现与测试用例test/windows/WslcSdkTests.cpp#L839-L1014该 API 的全部边界行为可归纳为下表场景行为依据portMappings NULL且portMappingCount ! 0返回E_INVALIDARGwslcsdk.cpp#L1046测试 #L845portMappings ! NULL且portMappingCount 0返回E_INVALIDARG同上测试 #L853portMappings NULL且portMappingCount 0成功S_OK等价于清空端口映射测试 #L860windowsAddress-ss_family不是AF_INET/AF_INET6返回E_INVALIDARGwslcsdk.cpp#L1050-L1054测试 #L1012protocol不是WSLC_PORT_PROTOCOL_TCP0返回E_NOTIMPLwslcsdk.cpp#L1056-L1057网络模式为 NONE 却配置端口映射设置 API 本身成功但WslcCreateContainer返回E_INVALIDARG测试 #L863-L878最后一条特别值得注意设置成功不等于创建成功。网络模式与端口映射的语义冲突被推迟到容器创建阶段才暴露因此最佳实践是在调用 WslcCreateContainer 后统一检查其返回值与errorMessage输出参数。7. 在 WinRT 封装层中的调用方式WslcSDK 除了 C 接口外还在 src/windows/WslcSDK/winrt 下提供了 WinRT 投影层。其中 src/windows/WslcSDK/winrt/ContainerSettings.cpp#L269-L284 展示了该 API 在封装侧的典型用法——先将 WinRT 集合中的PortMapping投影对象批量转换为底层结构体数组再一次性提交if (m_portMappings.Size() 0) { m_portMappingsStructs.clear(); m_portMappingsStructs.reserve(m_portMappings.Size()); for (auto const portMapping : m_portMappings) { if (!portMapping) { throw winrt::hresult_error(E_POINTER, LPort mappings collection contains a null element); } m_portMappingsStructs.push_back(GetStruct(portMapping)); } winrt::check_hresult(WslcSetContainerSettingsPortMappings( m_containerSettings.get(), m_portMappingsStructs.data(), static_castuint32_t(m_portMappingsStructs.size()))); }可以看到封装层在调用前做了两个额外的约定映射集合为空Size() 0时不会调用本 API保持默认无映射集合中出现空元素则直接抛出E_POINTER。同时通过winrt::check_hresult将任何失败HRESULT转换为 WinRT 异常符合 WinRT 侧的惯例。8. 与其他容器 API 的关系与调用顺序WslcSetContainerSettingsPortMappings属于 Container APIs 中 OPTIONAL CONTAINER SETTINGS 一组。与同组的兄弟 APIWslcSetContainerSettingsName、WslcSetContainerSettingsInitProcess、WslcSetContainerSettingsNetworkingMode、WslcSetContainerSettingsHostName、WslcSetContainerSettingsDomainName、WslcSetContainerSettingsFlags、WslcSetContainerSettingsVolumes、WslcSetContainerSettingsNamedVolumes一样它们都遵循相同的生命周期约定WslcInitContainerSettings │ ▼ WslcSetContainerSettings* 按需多次调用端口映射是其中之一 │ ▼ WslcCreateContainer ──► WslcStartContainer ──► WslcGetContainerInitProcess / WslcCreateContainerProcess │ ▼ WslcStopContainer ──► WslcDeleteContainer ──► WslcReleaseContainer端口映射的写入期严格位于WslcInitContainerSettings之后、WslcCreateContainer之前一旦容器创建完成修改容器设置对象不会再影响已创建的容器。从 Container APIs 索引 可以看到端口映射只是众多可选设置之一实际项目中通常与网络模式、初始化进程、卷挂载等组合使用。9. 当前限制与注意事项基于 not-yet-implemented-apis.md 与源码校验逻辑使用本 API 时需注意仅支持 TCP传入WSLC_PORT_PROTOCOL_UDP会得到E_NOTIMPL。虽然 WslcPortProtocol 枚举同时定义了 TCP/UDP但当前仓库实现只接受 TCP数值 0。仅支持 IPv4/IPv6 地址族windowsAddress传入其他地址族如AF_UNIX会得到E_INVALIDARG且错误信息包含具体的下标索引。指针与计数必须配对NULL指针 非零计数、非空指针 零计数均属非法参数NULL 零计数是合法的清空映射写法。内存生命周期WslcSetContainerSettingsPortMappings内部保存的是调用方数组指针容器创建前请勿释放或改写该数组。与网络模式的配合设置端口映射前请确认网络模式不是WSLC_CONTAINER_NETWORKING_MODE_NONE否则容器创建阶段会失败。回调检查返回值设置阶段成功不代表创建阶段成功务必检查WslcCreateContainer的返回值与errorMessage输出。10. 小结WslcSetContainerSettingsPortMappings是 WSL WslcSDK 中暴露容器网络服务到 Windows 宿主机的端口映射设置入口。通过本篇文章你可以掌握函数签名与参数语义、WslcContainerPortMapping结构与WslcPortProtocol枚举的完整字段、官方示例及 IPv4/IPv6 绑定地址覆盖写法、源码层的三类参数校验规则指针配对、地址族、协议以及仓库测试用例所覆盖的全部边界行为。在实际开发中建议将本 API 与 WslcInitContainerSettings、WslcSetContainerSettingsNetworkingMode 和 WslcCreateContainer 组合使用并牢记当前实现仅支持 TCP、UDP 映射属于未实现能力。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表