diff --git a/README.md b/README.md index 9e969a2..ee12abd 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ ## 1、介绍 -WebClient 软件包是 RT_Thread 自主研发的,基于 HTTP 协议的客户端的实现,它提供设备与 HTTP Server 的通讯的基本功能。 +WebClient 软件包是 RT-Thread 自主研发的,基于 HTTP 协议的客户端的实现,它提供设备与 HTTP Server 的通讯的基本功能。 WebClient 软件包功能特点如下: - 支持 IPV4/IPV6 地址; -- 支持 GET/POST 命令; +- 支持 GET/POST 请求方法; - 支持文件的上传和下载功能; - 支持 HTTPS 加密传输; - 完善的头部数据添加和处理方式。 @@ -73,11 +73,11 @@ RT-Thread online packages ## 3、使用 WebClient 软件包 - 软件包详细介绍,请参考 [软件包介绍](docs/introduction.md) -- 如何从零开始使用,请参考 [用户手册](docs/user-guide.md) +- 详细的示例介绍,请参考 [示例文档](docs/samples.md) -- 完整的 API 文档,请参考 [API 手册](docs/api.md) +- 如何从零开始使用,请参考 [用户指南](docs/user-guide.md) -- 详细的示例介绍,请参考 [示例文档](docs/samples.md) +- 完整的 API 文档,请参考 [API 手册](docs/api.md) - 软件包工作原理,请参考 [工作原理](docs/principle.md) @@ -86,7 +86,7 @@ RT-Thread online packages ## 4、注意事项 - WebClient 软件包连接 HTTPS 服务器时需要开启 WebClient 中对 TLS 功能的支持。 - - WebClient 软件包版本更新(`V1.0.0 -> V2.0.0`)后软件包中函数接口和使用流程都有所变化,若开发者代码中使用之前接口,可以适配最新版本接口,或者在版本号配置中选择 `V1.0.0` 版本。 + - WebClient 软件包版本更新(`V1.0.0 -> 当前最新版 V2.0.0`)后软件包中函数接口和使用流程都有所变化,若开发者代码中使用之前接口,可以适配最新版本接口,或者在版本号配置中选择 `V1.0.0` 版本。 ## 5、联系方式 & 感谢 diff --git a/docs/README.md b/docs/README.md index df0ac79..b24af71 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,5 +14,4 @@ |[user-guide.md](user-guide.md) |使用指南| |[api.md](api.md) |API 说明| |[samples.md](samples.md) |示例说明| -|[port.md](port.md) |移植文档| diff --git a/docs/api.md b/docs/api.md index 77c9898..52e6d21 100644 --- a/docs/api.md +++ b/docs/api.md @@ -72,7 +72,7 @@ ## 发送数据 -`int webclient_read(struct webclient_session *session, unsigned char *buffer, size_t size);` +`int webclient_write(struct webclient_session *session, const unsigned char *buffer, size_t size);` 发送数据到连接的服务器。 @@ -88,7 +88,7 @@ ## 接收数据 -`int webclient_write(struct webclient_session *session, const unsigned char *buffer, size_t size);` +`int webclient_read(struct webclient_session *session, unsigned char *buffer, size_t size);` 从连接的服务器接收数据。 @@ -116,34 +116,34 @@ | **返回** | **描述** | |=0 | 设置超时成功 | -## 设置请求发送的头部信息 +## 在请求头中添加字段数据 `int webclient_header_fields_add(struct webclient_session *session, const char *fmt, ...);` -该函数用于创建会话之后和发送 GET 或 POST 请求之前,用于添加发送的请求的头部信息。 +该函数用于创建会话之后和发送 GET 或 POST 请求之前,用于添加请求头字段数据。 | 参数 | 描述 | |:------------------|:-----------------------------------| |session | 当前连接会话结构体指针 | -|fmt | 添加头部信息的表达式 | -|... | 添加头部信息的数据,为可变参数 | +|fmt | 添加字段数据的表达式 | +|... | 添加的字段数据,为可变参数 | | **返回** | **描述** | -| >0 | 成功添加的头部数据的长度 | +| >0 | 成功添加的字段数据的长度 | | <=0 | 添加失败或者头部数据长度超出 | -## 通过关键字获取头部信息数据 +## 通过字段名获取字段值数据 `const char *webclient_header_fields_get(struct webclient_session *session, const char *fields);` -该函数用于发送 GET 或 POST 请求之后,可以通过传入的头域名称获取对应的头域数据。 +该函数用于发送 GET 或 POST 请求之后,可以通过传入的字段名称获取对应的字段数据。 | 参数 | 描述 | |:------------------|:-----------------------------------| |session | 当前连接会话结构体指针 | -|fields | HTTP 头域名称 | -| **返回** | **描述** | +|fields | HTTP 字段名称 | +| **返回** | **描述** | |= NULL | 获取数据失败 | -|!= NULL | 成功获取的关键字对应的数据 | +|!= NULL | 成功获取的字段数据 | ## 接收响应数据到指定地址 diff --git a/docs/introduction.md b/docs/introduction.md index 74c5f8e..758d3bf 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,6 +1,6 @@ # 软件包介绍 -WebClient 软件包是 RT_Thread 自主研发的,基于 HTTP 协议的客户端的实现,它提供设备与 HTTP Server 的通讯的基本功能。 +WebClient 软件包是 RT-Thread 自主研发的,基于 HTTP 协议的客户端的实现,它提供设备与 HTTP Server 的通讯的基本功能。 ## 软件包目录结构 @@ -29,19 +29,19 @@ webclient ## 软件包功能特点 -WebClient 软胶包功能特点: +WebClient 软件包功能特点: - 支持 IPV4/IPV6 地址 WebClient 软件包会自动根据传入的 URI 地址的格式判断是 IPV4 地址或 IPV6 地址,并且从其中解析出连接服务器需要的信息,提高代码兼容性。 -- 支持 GET/POST 命令 +- 支持 GET/POST 请求方法 - HTTP 有多种命令类型(GET、POST、PUT、DELETE等),目前 WebClient 软件包支持 GET 和 POST 命令,这也是嵌入式设备最常用到的两个命令类型,满足设备开发需求。 + HTTP 有多种请求方法(GET、POST、PUT、DELETE等),目前 WebClient 软件包支持 GET 和 POST 请求方法,这也是嵌入式设备最常用到的两个命令类型,满足设备开发需求。 - 支持文件的上传和下载功能 - WebClient 软件包提供文件上传和下载的接口函数,方便用户直接通过 GET/POST 命令上传本地文件到服务器或者下载服务器文件到本地,文件操作需要文件系统支持,使用前需开启并完成文件系统的移植。 + WebClient 软件包提供文件上传和下载的接口函数,方便用户直接通过 GET/POST 请求方法上传本地文件到服务器或者下载服务器文件到本地,文件操作需要文件系统支持,使用前需开启并完成文件系统的移植。 - 支持 HTTPS 加密传输 @@ -49,7 +49,7 @@ WebClient 软胶包功能特点: - 完善的头部数据添加和处理方式 - HTTP头部信息用于确定当前请求或响应的信息,在发送 GET 请求时头部的拼接成为用户操作的一大难题,正常的做法是手动逐行输入或使用字符串拼接方式,WebClient 软件包中提供 `类正则表达式方式` 添加 GET 请求头部信息,方便用户使用。对于 POST 返回的头部信息,往往用户需要获取头部对应信息,WebClient 软件包同样提供了 `通过头域名称获取域值方式`,方便获取需要的数据。 + HTTP 头部信息用于确定当前请求或响应的数据和状态信息,在发送 GET/POST 请求时头部的拼接成为用户操作的一大难题,正常的做法是手动逐行输入或使用字符串拼接方式,WebClient 软件包中提供 `类正则表达式方式` 添加需要发送的请求头部信息,方便用户使用。对于请求返回的头部信息,往往用户需要获取头部字段数据,WebClient 软件包同样提供了 `通过字段名获取字段数据的方式`,方便获取需要的数据。 ## HTTP 协议介绍 diff --git a/docs/samples.md b/docs/samples.md index 46c9fd9..60c7cfe 100644 --- a/docs/samples.md +++ b/docs/samples.md @@ -9,29 +9,6 @@ WebClient 软件包提供两个 HTTP Client 示例程序, 分别用于演示软 | samples/webclient_get_sample.c | GET 请求测试例程 | | samples/webclient_post_sample.c | POST 请求测试例程 | -## 例程工作流程 - -本例程使用的测试网站是 RT-Thread 系统的官方网站。GET 请求示例可以从网站中获取并打印显示文件内容;POST 请求示例可以上传数据到测试网站,测试网站会响应相同的数据。 - -> HTTP 收发数据包括头部数据和实际数据两部分,以下称头部数据为 `header 数据`, 实际数据为 `body 数据`。 - -GET 请求示例流程: - -- 创建 client 会话结构体 -- client 发送 GET 请求 header 数据(使用默认header 数据) -- server 响应 header 数据和 body 数据 -- 打印 server 响应 body 数据 -- GET 请求测试完成/失败 - -POST 请求示例流程: - -- 创建 client 会话结构体 -- 拼接 POST 请求需要的 header 数据 -- client 发送拼接的 header 数据和 body 数据 -- server 响应 header 数据和 body 数据 -- 打印 server 响应 body 数据 -- POST 请求测试完成/失败 - ## 准备工作 ### 获取软件包 @@ -57,13 +34,27 @@ RT-Thread online packages ## 启动例程 +本例程使用的测试网站是 RT-Thread 系统的官方网站。GET 请求示例可以从网站中获取并打印显示文件内容;POST 请求示例可以上传数据到测试网站,测试网站会响应相同的数据。 + +> HTTP 收发数据包括头部数据和实际数据两部分,以下称头部数据为 `header 数据`, 实际数据为 `body 数据`。 + ### GET 请求示例 +GET 请求示例流程: + +- 创建 client 会话结构体 +- client 发送 GET 请求 header 数据(使用默认header 数据) +- server 响应 header 数据和 body 数据 +- 打印 server 响应 body 数据 +- GET 请求测试完成/失败 + +GET 请求示例使用方式有如下两种: + - 在 MSH 中使用命令 `web_get_test` 执行 GET 请求示例程序,可以获取并打印显示默认网址下载的文件信息,如下图 LOG 显示: ```shell msh />web_get_test -[I/WEB] webclient GET request response data : +webclient GET request response data : RT-Thread is an open source IoT operating system from China, which has strong scalability: from a tiny kernel running on a tiny core, for example ARM Cortex-M0, or Cortex-M3/4/7, to a rich feature system running on MIPS32, ARM Cortex-A8, ARM Cortex-A9 DualCore etc. msh /> @@ -73,11 +64,22 @@ msh /> ### POST 请求示例 +POST 请求示例流程如下: + +- 创建 client 会话结构体 +- 拼接 POST 请求需要的 header 数据 +- client 发送拼接的 header 数据和 body 数据 +- server 响应 header 数据和 body 数据 +- 打印 server 响应 body 数据 +- POST 请求测试完成/失败 + +POST 请求示例使用方式有如下两种: + - 在 MSH 中使用命令 `web_post_test` 执行 POST 请求示例程序,可以获取并打印显示响应数据(默认 POST 请求的地址是类似于回显的地址,会返回上传的数据),如下图 LOG 显示: ```shell msh />web_post_test -[I/WEB] webclient POST request response data : +webclient POST request response data : RT-Thread is an open source IoT operating system from China! msh /> ``` diff --git a/docs/user-guide.md b/docs/user-guide.md index 981a1dd..11e61ce 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -123,7 +123,6 @@ if ((resp_status = webclient_get(session, URI)) != 200) ret = -RT_ERROR; goto __exit; } - ``` 4. **接收响应的数据** @@ -135,7 +134,7 @@ if ((resp_status = webclient_get(session, URI)) != 200) ```c int content_pos = 0; /* 获取接收的响应数据长度 */ -int content_length = session->content_length; +int content_length = atoi(webclient_header_fields_get(session, "Content-Length")); /* 循环接收响应数据直到数据接收完毕 */ do @@ -178,166 +177,173 @@ WenClient 软件包对于 GET/POST 请求,分别提供了几种不同的使用 - 使用默认头部发送 GET 请求 ```c - struct webclient_session *session = NULL; +struct webclient_session *session = NULL; - session = webclient_create(1024); - - if(webclient_get(session, URI) != 200) - { - LOG_E("error!"); - } - - while(1) - { - webclient_read(session, buffer, bfsz); - ... - } - - webclient_close(session); +session = webclient_create(1024); + +if(webclient_get(session, URI) != 200) +{ + LOG_E("error!"); +} + +while(1) +{ + webclient_read(session, buffer, bfsz); + ... +} + +webclient_close(session); ``` - 使用自定义头部发送 GET 请求 ```c - struct webclient_session *session = NULL; +struct webclient_session *session = NULL; - session = webclient_create(1024); +session = webclient_create(1024); - webclient_header_fields_add(session, "User-Agent: RT-Thread HTTP Agent\r\n"); +webclient_header_fields_add(session, "User-Agent: RT-Thread HTTP Agent\r\n"); - if(webclient_get(session, URI) != 200) - { - LOG_E("error!"); - } - - while(1) - { - webclient_read(session, buffer, bfsz); - ... - } - - webclient_close(session); +if(webclient_get(session, URI) != 200) +{ + LOG_E("error!"); +} + +while(1) +{ + webclient_read(session, buffer, bfsz); + ... +} + +webclient_close(session); ``` - 发送获取部分数据的 GET 请求(多用于断点续传) ```c - struct webclient_session *session = NULL; +struct webclient_session *session = NULL; - session = webclient_create(1024); +session = webclient_create(1024); - if(webclient_get_position(URI, 100) != 206) - { - LOG_E("error!"); - } - - while(1) - { - webclient_read(session, buffer, bfsz); - ... - } - - webclient_close(session); +if(webclient_get_position(URI, 100) != 206) +{ + LOG_E("error!"); +} + +while(1) +{ + webclient_read(session, buffer, bfsz); + ... +} + +webclient_close(session); ``` - 使用 `webclient_response` 接收 GET 数据 - 多用于接收数据长度较小的情况。 + 多用于接收数据长度较小的 GET 请求。 ```c - struct webclient_session *session = NULL; - char *result; - - session = webclient_create(1024); +struct webclient_session *session = NULL; +char *result; - if(webclient_get(session, URI, header) != 200) - { - LOG_E("error!"); - } - - webclient_response(session, &result); - - free(result); - webclient_close(session); +session = webclient_create(1024); + +if(webclient_get(session, URI) != 200) +{ + LOG_E("error!"); +} + +webclient_response(session, &result); + +web_free(result); +webclient_close(session); ``` - 使用 `webclient_request` 函数发送并接收 GET 请求 + 多用于接收数据长度较小,且头部信息已经拼接给出的 GET 请求。 + ```c - char *result; +char *result; - webclient_request(URI, header, NULL, &result); +webclient_request(URI, header, NULL, &result); - free(result); +web_free(result); ``` ### POST 请求方式 - 分段数据 POST 请求 + 多用于上传数据量较大的 POST 请求,如:上传文件到服务器。 + ```c - struct webclient_session *session = NULL; +struct webclient_session *session = NULL; - session = webclient_create(1024); +session = webclient_create(1024); - /* 拼接必要的头部信息 */ - webclient_header_fields_add(session, "Content-Length: %d\r\n", post_data_sz); - webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n"); +/* 拼接必要的头部信息 */ +webclient_header_fields_add(session, "Content-Length: %d\r\n", post_data_sz); +webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n"); - /* 分段数据上传 webclient_post 第三个传输上传数据为 NULL,改为下面循环上传数据*/ - if( webclient_post(session, URI, NULL) != 200) - { - LOG_E("error!"); - } - - while(1) - { - webclient_write(session, post_data, 1024); - ... - } - - if( webclient_handle_response(session) != 200) - { - LOG_E("error!"); - } - - webclient_close(session); +/* 分段数据上传 webclient_post 第三个传输上传数据为 NULL,改为下面循环上传数据*/ +if( webclient_post(session, URI, NULL) != 200) +{ + LOG_E("error!"); +} + +while(1) +{ + webclient_write(session, post_data, 1024); + ... +} + +if( webclient_handle_response(session) != 200) +{ + LOG_E("error!"); +} + +webclient_close(session); ``` - 整段数据 POST 请求 + 多用于上传文件较小的 POST 请求。 + ```c - char *post_data = "abcdefg"; +char *post_data = "abcdefg"; - session = webclient_create(1024); - - /* 拼接必要的头部信息 */ - webclient_header_fields_add(session, "Content-Length: %d\r\n", strlen(post_data)); - webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n"); +session = webclient_create(1024); - if(webclient_post(session, URI, post_data) != 200); - { - LOG_E("error!"); - } - webclient_close(session); +/* 拼接必要的头部信息 */ +webclient_header_fields_add(session, "Content-Length: %d\r\n", strlen(post_data)); +webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n"); + +if(webclient_post(session, URI, post_data) != 200); +{ + LOG_E("error!"); +} +webclient_close(session); ``` - 使用 `webclient_request` 函数发送 POST 请求 + 多用于上传文件较小且头头部信息已经拼接给出的 POST 请求。 + ```c - char *post_data = "abcdefg"; - char *header = "xxx"; +char *post_data = "abcdefg"; +char *header = "xxx"; - webclient_request(URI, header, post_data, NULL); +webclient_request(URI, header, post_data, NULL); ``` - ## 常见问题 ### HTTPS 地址不支持 ```c -[web]not support https connect, please enable webclient https configure! +[E/WEB]not support https connect, please enable webclient https configure! ``` - 原因:使用 HTTPS 地址但是没有开启 HTTPS 支持。 @@ -347,7 +353,7 @@ WenClient 软件包对于 GET/POST 请求,分别提供了几种不同的使用 ### 头部数据长度超出 ```c -[web]not enough header buffer size(xxx)! +[E/WEB]not enough header buffer size(xxx)! ``` - 原因:添加的头部数据长度超过了最大支持的头部数据长度。 diff --git a/samples/webclient_get_sample.c b/samples/webclient_get_sample.c index 5c9d5c9..0184d14 100644 --- a/samples/webclient_get_sample.c +++ b/samples/webclient_get_sample.c @@ -87,7 +87,7 @@ int webclient_get_test(int argc, char **argv) goto __exit; } - rt_kprintf("webclient GET request response data :"); + rt_kprintf("webclient GET request response data :\n"); if(webclient_header_fields_get(session, "Content-Length")) { @@ -96,7 +96,7 @@ int webclient_get_test(int argc, char **argv) if (content_length < 0) { - rt_kprintf("The webclient GET request type is chunked.\n"); + rt_kprintf("webclient GET request type is chunked.\n"); do { bytes_read = webclient_read(session, buffer, GET_RESP_BUFSZ); diff --git a/samples/webclient_post_sample.c b/samples/webclient_post_sample.c index 4841968..fa54a8d 100644 --- a/samples/webclient_post_sample.c +++ b/samples/webclient_post_sample.c @@ -94,7 +94,7 @@ int webclient_post_test(int argc, char **argv) goto __exit; } - LOG_I("webclient POST request response data :"); + rt_kprintf("webclient POST request response data :\n"); do { bytes_read = webclient_read(session, buffer, POST_RESP_BUFSZ);