示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载导读本文围绕 Windows-classic-samples 仓库中的 HttpPurchaseOrderWithSslService 示例深入讲解如何基于 Windows Web Services APIWWS编写一个托管于 HTTP 之上的 PurchaseOrder采购订单SOAP 服务并通过 SSL 传输安全绑定WS_SSL_TRANSPORT_SECURITY_BINDING对通信进行加密。读完本文你将掌握 WWS 服务端的完整开发链路从 WSDL 契约定义、Wsutil.exe代码生成、服务契约函数表注册到服务主机Service Host的创建、打开与关闭再到运行前必须完成的 HTTP URL 预留与 SSL 证书注册等实操步骤。一、示例定位WWS 服务端 SSL 传输安全该示例的官方定位是演示 Windows Web Services API 如何使用服务主机Service Host在 HTTP 之上托管一个 PurchaseOrder 服务并启用 SSL 传输安全transport security。它属于 WWS 服务端server编程模型与之配套的客户端实现位于同仓库的 HttpPurchaseOrderWithSslClient两者通过https://localhost:8443/example这一端点地址对接。从文件组织看本示例目录结构非常精简HttpPurchaseOrderServiceWithSsl.cpp服务端全部核心逻辑PurchaseOrder.wsdl服务契约的 WSDL 定义HttpPurchaseOrderWithSslService.vcxprojVisual Studio 工程文件readme.txt补充的构建与运行说明。操作系统层面的最低要求为客户端 Windows 7、服务端 Windows Server 2008 R2。示例最初基于 Visual Studio 2013 Windows 8.1 编写但多数情况下可直接在更新版本的 Visual Studio 与 Windows 上无改动运行。二、WSDL 契约服务端一切代码的源头WWS 的编程模型以 WSDL 契约为核心。本示例的服务契约并非手写 C 结构而是由 PurchaseOrder.wsdl 描述再通过Wsutil.exe工具生成对应的.wsdl.c与.wsdl.h头文件供源码直接引用。该 WSDL 定义了一个命名空间为http://example.org的服务包含五类核心数据类型XSD 元素字段说明PurchaseOrderTypequantityxsd:int、productNamexsd:string下单请求OrderConfirmationTypeorderIDxsd:unsignedInt、expectedShipDatexsd:string下单响应GetOrderStatusTypeorderIDxsd:unsignedInt查询订单状态请求GetOrderStatusResponseTypeorderID、statusxsd:string查询订单状态响应OrderNotFoundFaultTypeorderIDxsd:unsignedInt订单不存在时的 Fault 细节在消息与操作层面IPurchaseOrder端口类型定义了Order与OrderStatus两个操作并通过wsaw:Action指定了各自的 SOAP Action如http://example.org/purchaseorder、http://example.org/getorderstatusOrderStatus操作还声明了OrderNotFoundfault。绑定PurchaseOrderBinding采用 SOAP 1.1 的 document/literal 风格soap:body useliteral/这也是本示例服务通信的传输协议基础。工程构建细节在 HttpPurchaseOrderWithSslService.vcxproj 中可以看到WSDL 被声明为CustomBuild项构建命令为Wsutil.exe /wsdl:PurchaseOrder.wsdl /out:.输出PurchaseOrder.wsdl.c与PurchaseOrder.wsdl.h两个文件并被编译进工程。因此修改 WSDL 后重新构建即可重新生成契约代码。三、源码深度解析从安全绑定到服务主机生命周期服务端全部逻辑集中在 HttpPurchaseOrderServiceWithSsl.cpp 中代码遵循典型的 WWS 服务端三步曲配置安全描述 → 配置服务端点 → 创建/打开/关闭服务主机。3.1 SSL 传输安全绑定的配置服务端点启用 HTTPS 的关键在于安全绑定security binding。源码在wmain入口中按以下顺序组装// 声明并初始化一个 SSL 传输安全绑定 WS_SSL_TRANSPORT_SECURITY_BINDING sslBinding {}; // 先清零结构体 sslBinding.binding.bindingType WS_SSL_TRANSPORT_SECURITY_BINDING_TYPE; // 设置绑定类型 // 声明并初始化所有安全绑定组成的数组 WS_SECURITY_BINDING* securityBindings[1] { sslBinding.binding }; // 声明并初始化安全描述 WS_SECURITY_DESCRIPTION securityDescription {}; securityDescription.securityBindings securityBindings; securityDescription.securityBindingCount WsCountOf(securityBindings);WS_SSL_TRANSPORT_SECURITY_BINDING是 WWS 提供的传输安全绑定结构通过bindingType WS_SSL_TRANSPORT_SECURITY_BINDING_TYPE将其登记为 SSL 传输绑定WS_SECURITY_DESCRIPTION聚合所有安全绑定此处仅一个后续挂接到服务端点上即完成安全配置。源码中有一行非常关键的注释值得特别注意NOTE: At the server, the SSL certificate for the listen URI must be registered with http.sys using a tool such as httpcfg.exe.也就是说仅仅在代码里配置绑定还不够——服务进程实际通过内核 HTTP 协议栈http.sys监听端口因此监听 URI 对应的 SSL 证书必须先在系统层面注册后文第 5 节详述。3.2 服务端点的组装端点endpoint是服务暴露的地址 通道 安全 契约的组合体serviceEndpoint.address.url.chars Lhttps://localhost:8443/example; // 监听地址 serviceEndpoint.address.url.length (ULONG)wcslen(serviceEndpoint.address.url.chars); serviceEndpoint.channelBinding WS_HTTP_CHANNEL_BINDING; // HTTP 通道绑定 serviceEndpoint.channelType WS_CHANNEL_TYPE_REPLY; // 回复型通道服务端 serviceEndpoint.securityDescription securityDescription; // 挂接安全描述 serviceEndpoint.contract purchaseOrderContract; // 挂接服务契约 serviceEndpoint.properties serviceProperties; serviceEndpoint.propertyCount WsCountOf(serviceProperties);值得注意的细节监听地址为https://localhost:8443/example即 8443 端口这与readme.txt中 netsh 预留示例使用的 80/443 端口不同运行前请按代码中的实际端口进行 URL 预留与证书配置通道类型为WS_CHANNEL_TYPE_REPLY对应服务端「一问一答」的 SOAP 消息模式端点属性中注册了关闭回调close channel callbackWS_SERVICE_ENDPOINT_PROPERTY_CLOSE_CHANNEL_CALLBACK其回调实现CloseChannelCallback使用InterlockedIncrement统计连接关闭次数当累计达到 300 次时通过SetEvent(closeServer)触发服务自行退出——这是本示例实现「自动收尾」的机制。3.3 服务契约的注册WSDL 生成的头文件中已包含PurchaseOrder_wsdl.contracts.PurchaseOrderBinding契约描述源码只需将它、默认契约与用户实现的函数表关联起来static const PurchaseOrderBindingFunctionTable purchaseOrderFunctions { PurchaseOrderImpl, // Order 操作实现 GetOrderStatusImpl // OrderStatus 操作实现 }; static const WS_SERVICE_CONTRACT purchaseOrderContract { PurchaseOrder_wsdl.contracts.PurchaseOrderBinding, // 来自生成头文件 NULL, // 不指定默认契约 purchaseOrderFunctions // 用户提供的函数表 };3.4 服务操作实现成功路径与 Fault 路径PurchaseOrderImplOrder 操作从操作上下文WS_OPERATION_CONTEXT中取出WS_OPERATION_CONTEXT_PROPERTY_HEAP在服务堆上分配并拷贝expectedShipDate固定返回L1/1/2006同时把orderID写为123。这展示了 WWS 服务端「输出参数由服务堆分配、由框架负责释放」的内存管理约定。GetOrderStatusImplOrderStatus 操作逻辑上分为两条路径。合法订单orderID 123同样从上下文取堆分配并返回订单状态字符串LPending非法订单orderID ! 123构造一个带细节的 SOAP Fault。源码先定义WS_FAULT_DETAIL_DESCRIPTIONfault 名OrderNotFound、命名空间http://example.com、Actionhttp://example.com/fault载荷元素类型WS_UINT32_TYPE然后调用WsSetFaultErrorDetail写入 fault 细节再用WsAddErrorString追加错误文本LInvalid order ID最后返回E_FAIL触发 fault 发送。这段代码同时是理解服务端 fault 序列化的最佳范本业务失败不应只返回一个 HRESULT而应通过WS_ERROR对象携带结构化 fault 细节返回给客户端。与之对应配套客户端在收到WS_E_ENDPOINT_FAULT_RECEIVED后会用WsGetFaultErrorDetail反向解析出_OrderNotFoundFaultType并打印Order %lu was not found——详见 HttpPurchaseOrderClientWithSsl.cpp 中 201~250 行的处理逻辑。3.5 服务主机生命周期创建 → 打开 → 等待 → 关闭主程序最后的流程清晰对应 README 中列出的相关 APIWsCreateError(...); // 创建错误对象承载丰富错误信息 closeServer CreateEvent(...); // 创建关闭事件 WsCreateServiceHost(serviceEndpoints, 1, NULL, 0, host, error); // ① 创建服务主机 WsOpenServiceHost(host, NULL, error); // ② 打开服务主机启动监听器 WaitForSingleObject(closeServer, INFINITE); // ③ 阻塞等待关闭信号 WsCloseServiceHost(host, NULL, error); // ④ 关闭服务主机 WsFreeServiceHost(host); // ⑤ 释放服务主机 WsFreeError(error); // 释放错误对象其中WsOpenServiceHost会真正启动 http.sys 侧的监听器一旦任意通道关闭计数达到 300closeServer事件被置位服务正常关闭。整个代码库还封装了PrintError工具函数通过WsGetErrorProperty/WsGetErrorString把WS_ERROR中的多条错误字符串逐条打印出来便于排查问题。3.6 工程链接配置从 HttpPurchaseOrderWithSslService.vcxproj 可以确认工程为控制台应用SubSystemConsole、CharacterSetUnicode支持 Win32/ARM/x64 与 Debug/Release 六种配置链接阶段依赖以下库webservices.lib; crypt32.lib; rpcrt4.lib; Iphlpapi.lib其中webservices.lib是 WWS 运行时库crypt32.lib用于证书与加密操作支持。四、构建示例按照 README 的说明构建步骤为用 Visual Studio 2013Windows 8.1 任意 SKU或更新版本打开HttpPurchaseOrderWithSslService.sln位于 cpp 目录按 F7Visual Studio 2013 也可用 F6或通过菜单 Build → Build Solution 构建输出默认生成在\Debug或Release目录下。readme.txt补充了两点注意事项构建前可通过 Build 菜单的 Configuration Manager 切换目标平台Win32/x64/ARM若在 Windows XP / Vista / Server 2003 / Server 2008 等旧系统上运行可能需要先安装包含 Windows Web Services API 运行时 DLL 的 Windows Update详情以 MSDN 文档为准。五、运行前的系统准备URL 预留与 SSL 证书注册这是 WWS HTTP 服务示例最容易踩坑的环节也是readme.txt花了大量篇幅说明的部分。5.1 预留 HTTP URLURL ACL为了让非管理员权限的 Visual Studio 也能运行服务端示例必须先以管理员身份为 HTTP 命名空间预留 URL。readme.txt给出的命令如下CMD 环境netsh http add urlacl urlhttp://:80/example user%USERDOMAIN%\%USERNAME% netsh http add urlacl urlhttps://:443/example user%USERDOMAIN%\%USERNAME%若使用提升权限的 PowerShellnetsh http add urlacl urlhttp://:80/example user$env:USERDOMAIN\$env:USERNAME netsh http add urlacl urlhttps://:443/example user$env:USERDOMAIN\$env:USERNAME需要特别指出本示例源码实际监听的是https://localhost:8443/example因此实际操作时应把端口替换为 8443例如netsh http add urlacl urlhttps://:8443/example user%USERDOMAIN%\%USERNAME%不再需要时可在管理员 CMD 或 PowerShell 中删除预留netsh http delete urlacl urlhttp://:80/example netsh http delete urlacl urlhttps://:443/example同样若改用 8443 端口则删除对应条目。5.2 向 http.sys 注册 SSL 证书源码注释明确指出服务端监听 URI 的 SSL 证书必须通过httpcfg.exe之类的工具注册到 http.sys。这是 HTTPS 服务能够正常握手的前提——仅配置WS_SSL_TRANSPORT_SECURITY_BINDING而不注册证书服务在WsOpenServiceHost阶段就会失败。实际部署时需要在目标机器上为localhost:8443或实际监听 URI安装并绑定一张受信任的服务器证书并将证书指纹与端口/主机名关联注册到 http.sys。六、运行示例并验证构建并完成系统准备后在 Visual Studio 中按 F5带调试运行或 CtrlF5不带调试运行也可以从 Debug 菜单选择对应选项程序启动后服务主机开始监听https://localhost:8443/example控制台会在每次收到Order请求时打印quantity, productName例如100, Pencil同时构建并运行配套的 HttpPurchaseOrderWithSslClient 客户端它会循环 100 次调用PurchaseOrderBinding_Order提交 100 支 Pencil 的订单收到订单号与预计发货日期调用PurchaseOrderBinding_OrderStatus查询状态得到Pending故意使用非法订单号321触发服务端 Fault客户端捕获WS_E_ENDPOINT_FAULT_RECEIVED后解析出Order 321 was not found随后WsResetError复位错误对象继续下一轮。由此可以完整验证「SSL 加密通道 → SOAP 请求/响应 → 结构化 Fault 双向传递」整条链路。服务端在通道关闭累计达到 300 次后自动关闭并退出。七、关键 API 速查README 的 Related topics 部分列出了本示例涉及的核心 API整理如下便于检索与对照源码API / 结构在本示例中的角色WS_SSL_TRANSPORT_SECURITY_BINDING声明 SSL 传输安全绑定绑定类型为WS_SSL_TRANSPORT_SECURITY_BINDING_TYPEWS_SERVICE_CONTRACT将生成的 WSDL 契约与用户回调函数表关联WS_FAULT_DETAIL_DESCRIPTION描述自定义 faultOrderNotFound的 Action、元素与载荷类型WS_XML_STRING定义 fault 名称、命名空间、Action 等 XML 字符串常量WsCreateServiceHost基于端点数组创建服务主机WsOpenServiceHost打开服务主机并启动监听器WsCloseServiceHost停止服务主机监听WsFreeServiceHost释放服务主机资源WsGetOperationContextProperty从操作上下文获取属性如WS_OPERATION_CONTEXT_PROPERTY_HEAP这些 API 共同构成了 WWS 服务端编程模型的最小闭环理解它们即可举一反三扩展到仓库中其余 HTTP/SSL 服务示例如 HttpCalculatorWithSslService、HttpServerWithSsl等。八、小结HttpPurchaseOrderWithSslService 示例浓缩了 Windows Web Services API 服务端开发的全部要点WSDL 驱动契约生成、SSL 传输安全绑定装配、服务契约注册、服务操作与 Fault 实现、服务主机生命周期管理以及 http.sys 层面的 URL 预留与证书注册。对照仓库中配套的 客户端示例可以快速搭建一套端到端加密的 SOAP 服务通信原型。需要强调的是该示例仅用于教学演示代码未针对生产环境做过加固与测试实际落地时务必结合证书管理、访问控制与错误处理进行改造。赞分享示例工程【免费下载链接】Windows-classic-samplesThis repo contains samples that demonstrate the API used in Windows classic desktop applications.项目地址https://gitcode.com/gh_mirrors/wi/Windows-classic-samples点击查看免费下载相关推荐Windows-classic-samplesHttpPurchaseOrderService 示例——基于 Windows Web Services API 托管 HTTP 采购订单服务Windows classic samplesHttpPurchaseOrderService 示例——基于 Windows Web Services API示例工程Windows Web ServicesWWSHTTPS 安全客户端实战HttpPurchaseOrderWithSslClient 源码全解析Windows Web ServicesWWSHTTPS 安全客户端实战HttpPurchaseOrderWithSslClient 源码全解析 导读 本示例工程使用 Windows Web Services API 构建 SSL 传输安全的 HTTP 服务器Windows-classic-samples HttpServerWithSsl 实战解析使用 Windows Web Services API 构建 SSL 传输安全的 HTTP 服务器Windows classic samples HttpSe示例工程上一篇TensorFlow Serving SavedModel 模型预热Warmup实战指南下一篇ComfyUI ControlNet AuxAI图像控制的革命性解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考