windows C++-windows C++-使用任务和 XML HTTP 请求进行连接(二)

server/2024/10/11 7:12:24/

6.  在 HttpRequest.h 中,添加此代码:

namespace Web
{namespace Details
{// 用于执行异步HTTP请求的实用程序类。
// 此类一次只支持一个未完成的请求。
class HttpRequest
{
public:HttpRequest();int GetStatusCode() const{return statusCode;}std::wstring const& GetReasonPhrase() const{return reasonPhrase;}// Whether the response has been completely received, if using ReadAsync().bool IsResponseComplete() const{return responseComplete;}// Start an HTTP GET on the specified URI.  The returned task completes once the entire response// has been received, and the task produces the HTTP response text.  The status code and reason// can be read with GetStatusCode() and GetReasonPhrase().concurrency::task<std::wstring> GetAsync(Windows::Foundation::Uri^ uri, concurrency::cancellation_token cancellationToken = concurrency::cancellation_token::none());// Start an HTTP POST on the specified URI, using a string body.  The returned task produces the // HTTP response text.  The status code and reason can be read with GetStatusCode() and GetReasonPhrase().concurrency::task<std::wstring> PostAsync(Windows::Foundation::Uri^ uri,PCWSTR contentType,IStream* postStream,uint64 postStreamSizeToSend,concurrency::cancellation_token cancellationToken = concurrency::cancellation_token::none());// Start an HTTP POST on the specified URI, using a stream body.  The returned task produces the// HTTP response text.  The status code and reason can be read with GetStatusCode() and GetReasonPhrase().concurrency::task<std::wstring> PostAsync(Windows::Foundation::Uri^ uri,const std::wstring& str,concurrency::cancellation_token cancellationToken = concurrency::cancellation_token::none());// Send a request but don't return the response.  Instead, let the caller read it with ReadAsync().concurrency::task<void> SendAsync(const std::wstring& httpMethod,Windows::Foundation::Uri^ uri,concurrency::cancellation_token cancellationToken = concurrency::cancellation_token::none());// Read a chunk of data from the HTTP response, up to a specified length or until we reach the end// of the response, and store the value in the provided buffer.  This is useful for large content,// enabling the streaming of the result.concurrency::task<void> ReadAsync(Windows::Storage::Streams::IBuffer^ readBuffer,unsigned int offsetInBuffer,unsigned int requestedBytesToRead);static void CreateMemoryStream(IStream **stream);private:// Start a download of the specified URI using the specified method.  The returned task produces the// HTTP response text.  The status code and reason can be read with GetStatusCode() and GetReasonPhrase().concurrency::task<std::wstring> DownloadAsync(PCWSTR httpMethod,PCWSTR uri, concurrency::cancellation_token cancellationToken,PCWSTR contentType,IStream* postStream,uint64 postStreamBytesToSend);// Referenced pointer to the callback, if using SendAsync/ReadAsync.Microsoft::WRL::ComPtr<Details::HttpRequestBuffersCallback> buffersCallback;int statusCode;std::wstring reasonPhrase;// Whether the response has been completely received, if using ReadAsync().bool responseComplete;
};}

7. 在 HttpRequest.cpp 中,先定义一个类HttpRequestStringCallback :

#include "pch.h"
#include "HttpRequest.h"
#include <robuffer.h>
#include <shcore.h>using namespace concurrency;
using namespace Microsoft::WRL;
using namespace Platform;
using namespace std;
using namespace Web;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;//当只需要完整的响应时,使用IXMLHTTPRequest2Callback的实现。
//在处理收到的响应数据块时,请改用HttpRequestBuffersCallback。
class HttpRequestStringCallback : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IXMLHTTPRequest2Callback, FtmBase>
{
public:HttpRequestStringCallback(IXMLHTTPRequest2* httpRequest, cancellation_token ct = concurrency::cancellation_token::none()) :request(httpRequest), cancellationToken(ct){// Register a callback function that aborts the HTTP operation when // the cancellation token is canceled.if (cancellationToken != cancellation_token::none()){registrationToken = cancellationToken.register_callback([this]() {if (request != nullptr) {request->Abort();}});}}// 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;}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Called when a portion of the entity body has been received.IFACEMETHODIMP OnDataAvailable(IXMLHTTPRequest2*, ISequentialStream*){return S_OK;}// Called when the entire entity response has been received.IFACEMETHODIMP OnResponseReceived(IXMLHTTPRequest2*, ISequentialStream* responseStream){wstring wstr;HRESULT hr = ReadUtf8StringFromSequentialStream(responseStream, wstr);// We must not propagate exceptions back to IXHR2.try{completionEvent.set(make_tuple<HRESULT, wstring>(move(hr), move(wstr)));}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Simulate the functionality of DataReader.ReadString().// This is needed because DataReader requires IRandomAccessStream and this// code has an ISequentialStream that does not have a conversion to IRandomAccessStream like IStream does.HRESULT ReadUtf8StringFromSequentialStream(ISequentialStream* readStream, wstring& str){// Convert the response to Unicode wstring.HRESULT hr;// Holds the response as a Unicode string.wstringstream ss;while (true){ULONG cb;char buffer[4096];// Read the response as a UTF-8 string.  Since UTF-8 characters are 1-4 bytes long,// we need to make sure we only read an integral number of characters.  So we'll// start with 4093 bytes.hr = readStream->Read(buffer, sizeof(buffer) - 3, &cb);if (FAILED(hr) || (cb == 0)){break; // Error or no more data to process, exit loop.}if (cb == sizeof(buffer) - 3){ULONG subsequentBytesRead;unsigned int i, cl;// Find the first byte of the last UTF-8 character in the buffer.for (i = cb - 1; (i >= 0) && ((buffer[i] & 0xC0) == 0x80); i--);// Calculate the number of subsequent bytes in the UTF-8 character.if (((unsigned char)buffer[i]) < 0x80){cl = 1;}else if (((unsigned char)buffer[i]) < 0xE0){cl = 2;}else if (((unsigned char)buffer[i]) < 0xF0){cl = 3;}else{cl = 4;}// Read any remaining bytes.if (cb < i + cl){hr = readStream->Read(buffer + cb, i + cl - cb, &subsequentBytesRead);if (FAILED(hr)){break; // Error, exit loop.}cb += subsequentBytesRead;}}// First determine the size required to store the Unicode string.int const sizeRequired = MultiByteToWideChar(CP_UTF8, 0, buffer, cb, nullptr, 0);if (sizeRequired == 0){// Invalid UTF-8.hr = HRESULT_FROM_WIN32(GetLastError());break;}unique_ptr<char16[]> wstr(new(std::nothrow) char16[sizeRequired + 1]);if (wstr.get() == nullptr){hr = E_OUTOFMEMORY;break;}// Convert the string from UTF-8 to UTF-16LE.  This can never fail, since// the previous call above succeeded.MultiByteToWideChar(CP_UTF8, 0, buffer, cb, wstr.get(), sizeRequired);wstr[sizeRequired] = L'\0'; // Terminate the string.ss << wstr.get(); // Write the string to the stream.}str = SUCCEEDED(hr) ? ss.str() : wstring();return (SUCCEEDED(hr)) ? S_OK : hr; // Don't return S_FALSE.}// 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{completionEvent.set(make_tuple<HRESULT, wstring>(move(hrError), wstring()));}catch (std::bad_alloc&){hr = E_OUTOFMEMORY;}return hr;}// Retrieves the completion event for the HTTP operation.task_completion_event<tuple<HRESULT, wstring>> const& GetCompletionEvent() const{return completionEvent; }int GetStatusCode() const{return statusCode;}wstring GetReasonPhrase() const{return reasonPhrase;}private:~HttpRequestStringCallback(){// Unregister the callback.if (cancellationToken != cancellation_token::none()){cancellationToken.deregister_callback(registrationToken);}}// Signals that the download operation was canceled.cancellation_token cancellationToken;// Used to unregister the cancellation token callback.cancellation_token_registration registrationToken;// The IXMLHTTPRequest2 that processes the HTTP request.ComPtr<IXMLHTTPRequest2> request;// Task completion event that is set when the // download operation completes.task_completion_event<tuple<HRESULT, wstring>> completionEvent;int statusCode;wstring reasonPhrase;
};

8. 接下来继续完成这个类的成员函数代码的添加:

//将字节从顺序流复制到提供的缓冲区中,直到
//我们到达了一个或另一个的终点。
unsigned int Web::Details::HttpRequestBuffersCallback::ReadData(_Out_writes_(outputBufferSize) byte* outputBuffer,unsigned int outputBufferSize)
{// Lock the data event while doing the read, to ensure that any bytes we don't read will// result in the correct event getting triggered.concurrency::critical_section::scoped_lock lock(dataEventLock);ULONG bytesRead;CheckHResult(dataStream.Get()->Read(outputBuffer, outputBufferSize, &bytesRead));if (bytesRead < outputBufferSize){// We need to reset the data event, which we can only do by creating a new one.dataEvent = task_completion_event<void>();}return bytesRead;
}

9. 在代码中加入对完成任务的处理函数:

//以异常安全的方式创建一个在数据可用时完成的任务。
task<void> Web::Details::HttpRequestBuffersCallback::CreateDataTask()
{concurrency::critical_section::scoped_lock lock(dataEventLock);return create_task(dataEvent, cancellationToken);
}HttpRequest::HttpRequest() : responseComplete(true), statusCode(200)
{
}

http://www.ppmy.cn/server/130017.html

相关文章

python全栈开发是什么?

全栈指掌握多种技能&#xff0c;并能利用多种技能独立完成产品。通俗的说就是与这项技能有关的都会&#xff0c;都能独立完成。 python&#xff0c;因为目前很火&#xff0c;能开发的项目很多。例如&#xff1a;web前端后端&#xff0c;自动化运维&#xff0c;软件、小型游戏开…

毕设---中国移动网站平台管理系统的设计与实现

本系统采用技术 采用J2EE框架&#xff08;Struts 2、Spring、iBATIS&#xff09; iBATIS&#xff0c;FreeMarker&#xff0c;Lucene&#xff0c;Struts 2等技术 毕业论文—任务书 毕业设计基本内容和要求&#xff1a; 基本要求本毕业设计要求学生通过实习工作&#xff0c;让…

LangChain中使用Prompt01

1.引入提示模板 from langchain.prompts import (SystemMessagePromptTemplate,AIMessagePromptTemplate,HumanMessagePromptTemplate, )2.设置系统提示 system_template_text"你是一位专业的翻译&#xff0c;能够将{input_language}翻译成{output_language}&#xff0c…

android studio可用下载地址

AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 在此记录一下

Elasticsearch 索引数据预处理

pipeline 在文档写入 ES 之前&#xff0c;对数据进行预处理&#xff08;ingest&#xff09;工作通过定义 pipeline 和 processors 实现。 注意&#xff1a;数据预处理必须在 Ingest node 节点处理&#xff0c;ES 默认所有节点都是 Ingest node。 如果需要禁用 Ingest &#x…

智能EDA小白从0开始 —— DAY15 PADS

PADS&#xff08;Personal Automated Design System&#xff09;作为一款由Mentor Graphics公司推出的电子设计自动化&#xff08;EDA&#xff09;软件&#xff0c;自1986年面世以来&#xff0c;一直在电子设计领域扮演着重要角色。PADS以其模块化的设计、丰富的功能和稳定的性…

服装生产管理的数字化转型:SpringBoot框架

4 系统设计 4.1 系统结构设计 在结构设计过程中&#xff0c;首先对系统进行需求分析&#xff0c;然后进行系统初步设计&#xff0c;将系统功能模块细化&#xff0c;具体分析每一个功能模块具体应该首先哪些功能&#xff0c;最后将各个模块进行整合&#xff0c;实现系统结构的…

GitHub Copilot 使用手册(一)--配置

一、 什么是GitHub Copilot GitHub Copilot 是GitHub和OpenAI合作开发的一个人工智能工具&#xff0c;在使用Visual Studio Code、Microsoft Visual Studio、Vim、Cursor或JetBrains等IDE时可以协助用户编写代码等工作&#xff0c;实现虚拟的结对编程。 二、 GitHub Copilot …