From 34c8a553e7175965694325fa9dbaaa72bb6789b1 Mon Sep 17 00:00:00 2001 From: hu-kai45 Date: Tue, 4 Jul 2023 21:45:31 +0800 Subject: [PATCH] =?UTF-8?q?README=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hu-kai45 --- README.md | 44 ++++++++++++++++++++++++++++++ README_zh.md | 48 +++++++++++++++++++++++++++++++-- figures/inner_structure.png | Bin 88947 -> 51145 bytes figures/inner_structure_zh.png | Bin 90700 -> 0 bytes figures/structure.png | Bin 43025 -> 30414 bytes figures/structure_zh.png | Bin 47626 -> 0 bytes 6 files changed, 90 insertions(+), 2 deletions(-) delete mode 100644 figures/inner_structure_zh.png delete mode 100644 figures/structure_zh.png diff --git a/README.md b/README.md index 50c5c57..0336ebb 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,54 @@ upper layer applications build HTTP communication capabilities. ![structure](./figures/structure.png) +The following is the description information for the key fields in the figure above: + +- `APP`: A direct user facing upper level application that requires the ability to upload and download. +- `request`: The component in the OpenHarmony system service layer that provides upload and download capabilities. +- `netstack`: The system component in the OpenHarmony system service layer that provides network protocol stack functionality. +- `ylong_http`: The system component in the OpenHarmony system service layer that provides HTTP protocol stack functionality. + - `ylong_http_client`: One of the modules under `ylong_http` provides HTTP client capabilities. + - `ylong_http`: One of the modules under `ylong_http` provides the basic components of HTTP. +- `ylong_runtime`: Rust asynchronous runtime library provided by `ylong` in the system service layer. +- `tokio`: The third-party rust asynchronous runtime library commonly used in the industry. +- `OpenSSL`: A commonly used third-party TLS implementation library in the industry. + ### The internal structure of ylong_http ![inner_structure](./figures/inner_structure.png) +The following is the description information for the key fields in the figure above: + +- `ylong_http_client`: One of the modules under `ylong_http` provides HTTP client capabilities. + - `sync_impl`: Synchronize HTTP client implementation without relying on any runtime. + - `Client`: Synchronize HTTP clients to send HTTP requests. + - `ConnectionPool`: Manage all `Dispatchers`. + - `Dispatcher`: Manage the usage rights of `Connections`. + - `Connector`: Used to create a synchronous connection. + - `Connections`: Synchronous TCP or TLS connections, etc. + - `async_impl`: Asynchronous HTTP client implementation. + - `Client`: Asynchronous HTTP client used to send HTTP requests. + - `ConnectionPool`: Manage all `Dispatchers`. + - `Dispatcher`: Manage the usage rights of `Connections`. + - `Connector`: Used to create an asynchronous connection. + - `Connections`: Asynchronous TCP or TLS connections, etc. + - `Util`: Contains common components for both synchronous and asynchronous HTTP client implementations. + - `Redirect`: HTTP automatic redirection policy. + - `Proxy`: HTTP proxy policy. + - `Pool`: Universal Connection pool implementation. + - `OpenSSL_adapter`: OpenSSL Rust adaptation layer. +- `ylong_http`: One of the modules under `ylong_http` provides the basic components of HTTP. + - `Request`: HTTP Request implementation. + - `Response`: HTTP Response implementation. + - `Body`: HTTP message body implementation. + - `TextBody`: HTTP message body in plain text. + - `EmptyBody`: Empty message body implementation. + - `Mime`: Multipart message body implementation. + - `ylong_http`: ChunkBody message body implementation. + - `H1`: HTTP1 related component implementation. + - `H2`: HTTP2 related component implementation. + - `H3`: HTTP3 related component implementation. + ### ylong_http_client crate `ylong_http_client` crate supports HTTP client functionality and allows users diff --git a/README_zh.md b/README_zh.md index ece1ab8..fcac8e2 100644 --- a/README_zh.md +++ b/README_zh.md @@ -10,10 +10,54 @@ ylong_http 协议栈主体使用 Rust 语言编写,为 OpenHarmony 的 Rust ylong_http 向 OpenHarmony 系统服务层中的网络协议栈模块提供 HTTP 协议支持,经由网络协议栈模块帮助上层应用建立 HTTP 通信能力。 -![structure](./figures/structure_zh.png) +![structure](./figures/structure.png) + +以下是对于上图关键字段的描述信息: + +- `APP`:需要使用上传下载能力的直接面向用户的上层应用。 +- `request`:OpenHarmony 系统服务层提供上传下载能力的组件。 +- `netstack`:OpenHarmony 系统服务层提供网络协议栈功能的系统组件。 +- `ylong_http`:OpenHarmony 系统服务层提供 HTTP 协议栈功能的系统组件,使用 Rust 编写。 + - `ylong_http_client`:`ylong_http` 下的模块之一,提供 HTTP 客户端能力。 + - `ylong_http`:`ylong_http` 下的模块之一,提供 HTTP 的基础组件。 +- `ylong_runtime`:`ylong` 在系统服务层提供的 Rust 异步运行时库。 +- `tokio`:业界常用的第三方 Rust 异步运行时库。 +- `OpenSSL`:业界常用的第三方 TLS 实现库, C 语言实现。 ### ylong_http 的内部架构: -![inner_structure](./figures/inner_structure_zh.png) +![inner_structure](./figures/inner_structure.png) + +以下是对于上图关键字段的描述信息: + +- `ylong_http_client` 库:`ylong_http` 下的模块之一,提供 HTTP 客户端能力。 + - `sync_impl`:同步 HTTP 客户端实现,不依赖于任何运行时。 + - `Client`:同步 HTTP 客户端,用于发送 HTTP 请求。 + - `ConnectionPool`:管理所有的 `Dispatcher`。 + - `Dispatcher`:管理 `Connections` 的使用权。 + - `Connector`:用于创建同步连接。 + - `Connections`:同步的 TCP 或 TLS 连接等。 + - `async_impl`:异步 HTTP 客户端实现,不依赖于任何运行时。 + - `Client`:异步 HTTP 客户端,用于发送 HTTP 请求。 + - `ConnectionPool`:管理所有的 `Dispatcher`。 + - `Dispatcher`:管理 `Connections` 的使用权。 + - `Connector`:用于创建异步连接。 + - `Connections`:异步的 TCP 或 TLS 连接等。 + - `Util`:包含同步和异步 HTTP 客户端实现的共同组件。 + - `Redirect`:HTTP 自动重定向策略。 + - `Proxy`:HTTP 代理策略。 + - `Pool`:通用的连接池实现。 + - `OpenSSL_adapter`:OpenSSL Rust 适配层。 +- `ylong_http`:提供 HTTP 基础组件的模块。 + - `Request`:HTTP 请求实现 + - `Response`:HTTP 响应实现 + - `Body`:HTTP 消息体实现,提供基础的 trait。 + - `TextBody`:纯文本的消息体实现。 + - `EmptyBody`:空的消息体实现。 + - `Mime`:Multipart 消息体实现。 + - `ylong_http`:ChunkBody 消息体实现。 + - `H1`:HTTP1 相关组件实现。 + - `H2`:HTTP2 相关组件实现。 + - `H3`:HTTP3 相关组件实现。 ### ylong_http_client 库 diff --git a/figures/inner_structure.png b/figures/inner_structure.png index d70db04218492e0a96cf9b8206a2d461dc5de923..ee3031abba57639f18aa57800c21c6b6a80b162c 100644 GIT binary patch literal 51145 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ˤ`V1YohU8JwFx3 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