windows C++-使用任务和 XML HTTP 请求进行连接(一)
本文会演示如何将 IXMLHTTPRequest2 和 IXMLHTTPRequest2Callback 接口与任务结合使用,以将 HTTP GET 和 POST 请求发送至通用 Windows 平台 (UWP) 应用中的 Web 服务。 通过将 IXMLHTTPRequest2 与任务组合在一起,你可以编写通过其他任务编写的代码。 例如,可以使用下载任务作为任务链的一部分。 工作取消时,下载任务也会响应。
还可以使用 C++ REST SDK 从使用 C++ 应用的 UWP 应用或从桌面 C++ 应用来执行 HTTP 请求。
本文档首先演示如何创建 HttpRequest 及其支持类。 然后,演示如何从使用 C++ 和 XAML 的 UWP 应用使用此类。
IXMLHTTPRequest2 和 IXMLHTTPRequest2Callback 是建议在 UWP 应用中使用的接口。 还可以调整此示例,以用于桌面应用程序。
先决条件
Visual Studio 2017 及更高版本中的 UWP 支持是可选的。 若要安装它,请从 Windows“开始”菜单打开 Visual Studio 安装程序,并选择正在使用的 Visual Studio 版本。 单击“修改”按钮,确保选中“UWP 开发”磁贴。 在“可选组件”下,确保选中“C++ UWP 工具”。 对于 Visual Studio 2017,请使用 v141;对于 Visual Studio 2019,请使用 v142。
定义 HttpRequest、HttpRequestBuffersCallback 和 HttpRequestStringCallback 类
当您使用 IXMLHTTPRequest2 接口通过 HTTP 创建 Web 请求时,可以实现 IXMLHTTPRequest2Callback 接口来接收服务器响应并对其他事件做出响应。 此示例定义了 HttpRequest 类来创建 Web 请求,并定义了 HttpRequestBuffersCallback 和 HttpRequestStringCallback 类来处理响应。 HttpRequestBuffersCallback 和 HttpRequestStringCallback 类支持 HttpRequest 类;在应用程序代码中您只能使用 HttpRequest 类。
GetAsync 类的 PostAsync 和 HttpRequest 方法可以使您分别启动 HTTP GET 和 POST 操作。 这些方法使用 HttpRequestStringCallback 类以便将服务器响应作为字符串读取。 SendAsync 和 ReadAsync 方法使您能够对区块中的大型内容进行流式处理。 这些方法均返回 concurrency::task 以表示操作。 GetAsync 和 PostAsync 方法会产生 task<std::wstring> 值,其中 wstring 部分表示服务器的响应。 SendAsync 和 ReadAsync 方法将产生 task<void> 值;当发送和读取操作完成后这些任务将会完成。
因为 IXMLHTTPRequest2 接口是异步操作的,本示例使用 concurrency::task_completion_event 来创建一个任务,该任务将在回调对象完成或取消下载操作后完成。 HttpRequest 类从此任务创建基于任务的延续以设置最终结果。 HttpRequest 类使用基于任务的延续来确保,即使在前面的任务产生错误或取消的情况下,延续任务也会运行。 有关基于任务的延续的详细信息,请参阅任务并行
若要支持取消,HttpRequest、HttpRequestBuffersCallback 和 HttpRequestStringCallback 类将使用取消标记。 HttpRequestBuffersCallback 和 HttpRequestStringCallback 类使用 concurrency::cancellation_token::register_callback 方法使任务完成事件能够响应取消。
定义 HttpRequest 类
1. 在主菜单中,选择“文件”>“新建”>“项目”。
2. 使用 C++“空白应用(通用 Windows)”模板来创建空白 XAML 应用项目。 此示例将项目命名为 UsingIXMLHTTPRequest2。
3. 在项目中添加一个名为 HttpRequest.h 的标头文件和一个名为 HttpRequest.cpp 的源文件。
4. 在 pch.h 中,添加此代码:
#include <ppltasks.h>
#include <string>
#include <sstream>
#include <wrl.h>
#include <msxml6.h>
5. 在 HttpRequest.h 中,添加此代码:
我们会创建两个类,分别应对不同的情况,第一个类定义如下:
#pragma once
#include "pch.h"inline void CheckHResult(HRESULT hResult)
{if (hResult == E_ABORT){concurrency::cancel_current_task();}else if (FAILED(hResult)){throw Platform::Exception::CreateException(hResult);}
}namespace Web
{namespace Details
{// 当响应需要部分缓冲区时,使用IXMLHTTPRequest2Callback的实现。
// 当只需要完整的响应时,请改用HttpRequestStringCallback。
class HttpRequestBuffersCallback : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,IXMLHTTPRequest2Callback,Microsoft::WRL::FtmBase>
{
public:HttpRequestBuffersCallback(IXMLHTTPRequest2* httpRequest, concurrency::cancellation_token ct = concurrency::cancellation_token::none()) :request(httpRequest), cancellationToken(ct), responseReceived(false), dataHResult(S_OK), statusCode(200){// Register a callback function that aborts the HTTP operation when // the cancellation token is canceled.if (cancellationToken != concurrency::cancellation_token::none()){registrationToken = cancellationToken.register_callback([this]() {if (request != nullptr) {request->Abort();}});}dataEvent = concurrency::task_completion_event<void>();}// Called when the HTTP request is being redirected to a new URL.IFACEMETHODIMP OnRedirect(IXMLHTTPRequest2*, PCWSTR) {return S_OK;}// Called when HTTP headers have been received and processed.IFACEMETHODIMP OnHeadersAvailable(IXMLHTTPRequest2*, DWORD statusCode, PCWSTR reasonPhrase){HRESULT hr = S_OK;// We must not propagate exceptions back to IXHR2.try{this->statusCode = statusCode;this->reasonPhrase = reasonPhrase;concurrency::critical_section::scoped_lock lock(dataEventLock);dataEvent.set();}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Called when a portion of the entity body has been received.IFACEMETHODIMP OnDataAvailable(IXMLHTTPRequest2*, ISequentialStream* stream){HRESULT hr = S_OK;// We must not propagate exceptions back to IXHR2.try{// Store a reference on the stream so it can be accessed by the task.dataStream = stream;// The work must be done as fast as possible, and must not block this thread,// for example, waiting on another event object. Here we simply set an event// that can be processed by another thread.concurrency::critical_section::scoped_lock lock(dataEventLock);dataEvent.set();}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Called when the entire entity response has been received.IFACEMETHODIMP OnResponseReceived(IXMLHTTPRequest2* xhr, ISequentialStream* responseStream){responseReceived = true;return OnDataAvailable(xhr, responseStream);}// Called when an error occurs during the HTTP request.IFACEMETHODIMP OnError(IXMLHTTPRequest2*, HRESULT hrError) {HRESULT hr = S_OK;// We must not propagate exceptions back to IXHR2.try{concurrency::critical_section::scoped_lock lock(dataEventLock);dataHResult = hrError;dataEvent.set();}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Create a task that completes when data is available, in an exception-safe way.concurrency::task<void> CreateDataTask();HRESULT GetError() const{return dataHResult;}int GetStatusCode() const{return statusCode;}std::wstring const& GetReasonPhrase() const{return reasonPhrase;}bool IsResponseReceived() const{return responseReceived;}// Copy bytes from the sequential stream into the buffer provided until// we reach the end of one or the other.unsigned int ReadData(_Out_writes_(outputBufferSize) byte* outputBuffer,unsigned int outputBufferSize);private:~HttpRequestBuffersCallback(){// Unregister the callback.if (cancellationToken != concurrency::cancellation_token::none()){cancellationToken.deregister_callback(registrationToken);}}// Signals that the download operation was canceled.concurrency::cancellation_token cancellationToken;// Used to unregister the cancellation token callback.concurrency::cancellation_token_registration registrationToken;// The IXMLHTTPRequest2 that processes the HTTP request.Microsoft::WRL::ComPtr<IXMLHTTPRequest2> request;// Task completion event that is set when data is available or error is triggered.concurrency::task_completion_event<void> dataEvent;concurrency::critical_section dataEventLock;// We cannot store the error obtained from IXHR2 in the dataEvent since any value there is first-writer-wins,// whereas we want a subsequent error to override an initial success.HRESULT dataHResult;// Referenced pointer to the data stream.Microsoft::WRL::ComPtr<ISequentialStream> dataStream;// HTTP status code and reason returned by the server.int statusCode;std::wstring reasonPhrase;// Whether the response has been completely received.bool responseReceived;
};};
};
相关文章:
windows C++-使用任务和 XML HTTP 请求进行连接(一)
本文会演示如何将 IXMLHTTPRequest2 和 IXMLHTTPRequest2Callback 接口与任务结合使用,以将 HTTP GET 和 POST 请求发送至通用 Windows 平台 (UWP) 应用中的 Web 服务。 通过将 IXMLHTTPRequest2 与任务组合在一起,你可以编写通过其他任务编写的代码。 例…...

HTB:Oopsie[WriteUP]
目录 连接至HTB服务器并开启靶机 1.With what kind of tool can intercept web traffic? 2.What is the path to the directory on the webserver that returns a login page? 3.What can be modified in Firefox to get access to the upload page? 4.What is the acc…...
【JAVA高级】如何使用Redis加锁和解锁(一)、Lua脚本执行原理及流程
文章目录 加锁方法一:使用SETNX命令结合EXPIRE命令方法二:使用SET命令的扩展参数(NX和PX)方法三:使用Lua脚本 解锁方法一:简单删除key方法二:使用Lua脚本验证后删除key Lua脚本的执行原理&#…...
2024年使用宝塔面板轻松部署Java Web
以下是2024年最新图形化部署Java Web项目到CentOS系统的手把手教程: 一、准备工作 确保服务器环境:确保你的服务器已经安装了CentOS 7操作系统,并且已经安装了宝塔面板。如果还没有安装,可以参考之前的教程进行安装。下载Java W…...

闯关训练一:Linux基础
闯关任务:完成SSH连接与端口映射并运行hello_world.py 1.创建开发机 2.SSH连接 3. VS-Code 连接 选择 Linux 平台 ,输入密码 ,选择进入文件夹 4.端口映射 按照下文安装Docs pip install gradio 运行server.py import gradio as grdef …...

鸿蒙NEXT开发-ArkTS(基于最新api12稳定版)
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...
laravel延迟队列 取消未支付超时订单订单
1:生成待支付订单时,调用延迟队列 超过十五分钟未支付自动取消 use App\Jobs\endTask; use Illuminate\Support\Carbon; $resPost1 array("act" > "cy_order_cancel", "id" > $id); endTask::dispatch($resPos…...
解锁高效开发的秘密武器
在当今这个信息爆炸、技术日新月异的时代,编程工具的选择对于开发者来说至关重要。一个好的编程工具不仅能够简化代码编写,还能自动化任务、提升调试速度,甚至让团队协作更加顺畅。那么,哪款编程工具能让你的工作效率翻倍呢&#…...

【CSS】兼容处理
兼容前缀兼容查询 由于不同浏览器对CSS标准的支持程度不同,可能会导致在不同浏览器中出现样式差异。为了解决这个问题,需要采取一些措施来提高CSS的兼容性 兼容前缀 兼容前缀针对的浏览器-webkit-WebKit 内核浏览器,如:Safari 、…...

C语言线程
线程 多个进程中通过轮流使用CPU来完成自己的任务,如果多个进程的操作都一模一样那么CPU的开销就会很大,因为进程的地址都是私有的,如果CPU对相同的操作只执行一次,后面再遇到直接去获取即可,这样大大降低了CPU的开销…...

自闭症寄宿学校 vs. 日常教育:为孩子提供更多可能
在探索自闭症儿童的教育路径时,家长们往往面临一个重大的选择:是选择传统的日常教育环境,还是寻找专为自闭症儿童设计的寄宿学校?广州的星贝育园自闭症儿童寄宿制学校,以其独特的教育模式和全方位的关怀体系࿰…...
RxSwift系列(二)操作符
一、变换操作符:buffer、map、compactMap等 1.buffer buffer方法作用是缓冲组合,第一个参数是缓冲时间,第二个参数是缓冲个数,第三个参数是线程。缓存 Observable 中发出的新元素,当元素达到某个数量,或者…...

Gin框架简易搭建(3)--Grom与数据库
写在前面 项目地址 个人认为GORM 指南这个网站是相比较之下最为清晰的框架介绍 但是它在环境搭建阶段对于初学者而言不是很友好,尤其是使用mysql指令稍有不同,以及更新的方法和依赖问题都是很让人头疼的,而且这些报错并非逻辑上的…...

JavaScript模块化-CommonJS规范和ESM规范
1 ES6模块化 1.1 ES6基本介绍 ES6 模块是 ECMAScript 2015(ES6)引入的标准模块系统,广泛应用于浏览器环境下的前端开发。Node.js环境主要使用CommonJS规范。ESM使用import和export来实现模块化开发从而解决了以下问题: 全局作用…...

解决银河麒麟V10中的apt Lock异常
解决银河麒麟V10中的apt Lock异常 一、查找并杀掉apt进程二、删除锁文件三、重新尝试apt命令 💖The Begin💖点点关注,收藏不迷路💖 在使用银河麒麟V10的apt命令时,如果遇到lock异常,可以按以下步骤解决&…...

windows11环境安装lua及luarocks(踩坑篇)
一、lua安装及下载 官方地址: Lua Binaries Download 从这里就有坑了,下载后先解压win64_bin.zip,之后解压lib,用lib中的文件替换win64的,并把include文件夹复制过去,之后复制并重命名lua54,方…...

Glide基本用法及With方法源码解析
文章目录 引入优点 使用步骤导入依赖权限使用 其他用法占位符错误图片后备回调符圆角过渡动画大小调整gif缩略图 使用RequestOptions缓存机制设置缓存策略清理缓存 使用集成库OkHttpVolley with源码解析getRetrieverGlide.getinitializeGlide getRequestManagerRetriever Reque…...

html中的文本标签(含标签的实现案例)
目录 1.标题标签 2.标题标签的align属性 3.段落标签 4.水平线标签hr 5.换行标签br 6.文本样式标签font 编辑7.文本格式化标签 8.文本语义标签 1)时间time标签 2)文本高亮Mark标签 3)cite标签 9.特殊字符标签 10.图像标签img 附录ÿ…...

通信协议感悟
本文结合个人所学,简要讲述SPI,I2C,UART通信的特点,限制。 1.同步通信 UART,SPI,I2C三种串行通讯方式,SPI功能引脚为CS,CLK,MOSI,MISO;I2C功能引…...

IDEA几大常用AI插件
文章目录 前言列表GPT中文版TalkXBito AIIDEA自带的AI 前言 最近AI、GPT特别火,IDEA里面又有一堆插件支持GPT,所以做个专题比较一下各个GPT插件 列表 先看idea的plugins里支持哪些,搜索“GPT”之后得到的,我用下来感觉第一第二和…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...