

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# coreHTTP 基本多线程演示
<a name="core-http-bmt-demo"></a>

**重要**  <a name="deprecation-message-demo"></a>
该演示托管在已弃用的 Amazon-FreeRTOS 存储库中。当您创建新项目时，我们建议[从此处开始](freertos-getting-started-modular.md)。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的 FreeRTOS 项目，请参阅 [Amazon-FreeRTOS Github 存储库迁移指南](github-repo-migration.md)。

## 简介
<a name="core-http-bmt-demo-intro"></a>

此演示使用 [FreeRTOS 的线程安全队列](https://freertos.org/a00018.html)来保存待处理的请求和响应。此演示中有三个任务需要注意。
+ 主任务等待请求出现在请求队列中。它将通过网络发送这些请求，然后将响应放入响应队列中。
+ 请求任务创建要发送到服务器的 HTTP 库请求对象，并将它们放入请求队列中。每个请求对象都指定了应用程序为下载配置的 S3 文件的字节范围。
+ 响应任务等待响应出现在响应队列中。它会记录收到的每一个响应。

该基本多线程演示配置为使用仅具有服务器身份验证的 TLS 连接，这是 Amazon S3 HTTP 服务器所必需的。应用程序层身份验证使用[预签名 URL查询](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)中的[签名版本 4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 参数完成。

## 源代码组织
<a name="core-http-bmt-demo-source"></a>

演示项目已命名`http_demo_s3_download_multithreaded.c`，可以在`freertos/demos/coreHTTP/`目录和[ GitHub](https://github.com/aws/amazon-freertos/blob/main/demos/coreHTTP/http_demo_s3_download_multithreaded.c)网站上找到。

## 构建演示项目
<a name="core-http-bmt-demo-building"></a>

该演示项目使用 [Visual Studio 的免费社区版本](https://visualstudio.microsoft.com/vs/community/)。构建演示：

1. 在 Visual Studio IDE 中打开 `mqtt_multitask_demo.sln` Visual Studio 解决方案文件。

1. 从 IDE 的**构建**菜单中选择**构建解决方案**。

**注意**  
如果你使用的是 Microsoft Visual Studio 2017 或更早版本，则必须选择与你的版本兼容的**平台工具集**：**项目-> RTOSDemos 属性-> 平台工具**集。

## 配置演示项目
<a name="core-http-bmt-demo-configuring"></a>

该演示使用 [freerTOS\$1TCP TCP/IP 堆栈](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/index.html)，因此请按照为 TCP[/](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html)IP 入门项目提供的说明进行以下操作：

1. 安装[必备组件](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#prerequisites)（例如 WinPCap）。

1. （可选）[设置静态或动态 IP 地址、网关地址和网络掩码](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#static-dynamic)。

1. （可选）[设置 MAC 地址](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#mac-addr)。

1. 在主机上[选择一个以太网网络接口](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#network-interface)。

1. **重要的是**，在尝试运行 HTTP 演示之前，请先[测试您的网络连接](https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html#connectivity-test)。

## 配置 Amazon S3 HTTP 服务器连接
<a name="core-http-bmt-demo-configuring-connection"></a>

按照 *coreHTTP 基本下载演示*中有关[配置 Amazon S3 HTTP 服务器连接](core-http-s3-download-demo.md#core-http-s3-download-demo-configure-server)的说明进行操作。

## 功能
<a name="core-http-bmt-demo-functionality"></a>

此演示共创建三个任务：
+ 其一是通过网络发送请求和接收响应。
+ 其二是创建要发送的请求。
+ 其三是处理收到的响应。

在此演示中，主要任务：

1. 创建请求和响应队列。

1. 创建与服务器的连接。

1. 创建请求和响应任务。

1. 等待请求队列通过网络发送请求。

1. 将通过网络收到的响应放入响应队列中。

请求任务：

1. 创建每个范围请求。

响应任务：

1. 处理收到的每个响应。

## Typedefs
<a name="core-http-bmt-demo-typedefs"></a>

此演示定义以下结构来支持多线程。

**请求项目**

以下结构定义了要放入请求队列的请求项目。创建 HTTP 请求后，请求任务会将请求项目复制到队列中。

```
/**
 * @brief Data type for the request queue.
 *
 * Contains the request header struct and its corresponding buffer, to be
 * populated and enqueued by the request task, and read by the main task. The
 * buffer is included to avoid pointer inaccuracy during queue copy operations.
 */
typedef struct RequestItem
{
    HTTPRequestHeaders_t xRequestHeaders;
    uint8_t ucHeaderBuffer[ democonfigUSER_BUFFER_LENGTH ];
} RequestItem_t;
```

**响应项目**

以下结构定义了要放入响应队列的响应项目。通过网络收到响应后，主 HTTP 任务会将响应项目复制到队列中。

```
/**
 * @brief Data type for the response queue.
 *
 * Contains the response data type and its corresponding buffer, to be enqueued
 * by the main task, and interpreted by the response task. The buffer is
 * included to avoid pointer inaccuracy during queue copy operations.
 */
typedef struct ResponseItem
{
    HTTPResponse_t xResponse;
    uint8_t ucResponseBuffer[ democonfigUSER_BUFFER_LENGTH ];
} ResponseItem_t;
```

## 主要 HTTP 发送任务
<a name="core-http-bmt-demo-main-task"></a>

主要应用程序任务：

1. 解析主机地址的预签名 URL 以建立与 Amazon S3 HTTP 服务器的连接。

1. 解析 S3 存储桶中的对象路径的预签名 URL。

1. 使用 TLS 服务器身份验证连接到 Amazon S3 HTTP 服务器。

1. 创建请求和响应队列。

1. 创建请求和响应任务。

`prvHTTPDemoTask()` 函数会进行此设置，并提供演示状态。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L451-L650) 上找到。

在函数 `prvDownloadLoop()` 中，主任务会阻止并等待来自请求队列的请求。收到请求时，它会使用 API 函数 `HTTPClient_Send()` 发送请求。如果 API 函数成功，则会将响应放入响应队列中。

`prvDownloadLoop()` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L1071-L1174) 上找到。

## HTTP 请求任务
<a name="core-http-bmt-demo-request-task"></a>

请求任务在函数 `prvRequestTask` 中指定。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L778-L876) 上找到。

请求任务检索 Amazon S3 存储桶中文件的大小。这在函数 `prvGetS3ObjectFileSize` 中完成。将“Connection: keep-alive”标头添加到 Amazon S3 的此请求中，以便在发送响应后保持连接畅通。目前，Amazon S3 HTTP 服务器不支持使用预签名 URL 的 HEAD 请求，因此请求第 0 个字节。文件的大小包含在响应的 `Content-Range` 标头字段中。服务器的预期响应为 `206 Partial Content`；收到任何其他响应状态代码均为错误。

`prvGetS3ObjectFileSize` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L757-L774) 上找到。

检索文件大小后，请求任务会继续请求文件的各个范围。将每个范围请求放入请求队列中，以供主任务发送。文件范围由演示用户在宏 `democonfigRANGE_REQUEST_LENGTH` 中配置。使用函数 `HTTPClient_AddRangeHeader`，HTTP 客户端库 API 原生支持范围请求。函数 `prvRequestS3ObjectRange` 演示如何使用 `HTTPClient_AddRangeHeader()`。

函数 `prvRequestS3ObjectRange` 的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L694-L753) 上找到。

## HTTP 响应任务
<a name="core-http-bmt-demo-response-task"></a>

响应任务在响应队列中等待通过网络收到的响应。当主任务成功收到 HTTP 响应时，它会填充响应队列。此任务通过记录状态代码、标头和正文来处理响应。例如，现实世界中的应用程序可以通过将响应正文写入闪存来处理响应。如果响应状态代码不是 `206 partial content`，则该任务会通知主任务：演示应失败。响应任务在函数 `prvResponseTask` 中指定。此函数的源代码可以在 [GitHub](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/HTTP_S3_Download_Multithreaded/DemoTasks/S3DownloadMultithreadedHTTPExample.c#L961-L1047) 上找到。