使用指南

本节主要介绍 WebClient 软包的基本使用流程, 并针对使用过程中经常涉及到的结构体和重要 API 进行简要说明。

准备工作

首先需要下载 WebClient 软件包,并将软件包加入到项目中。在 BSP 目录下使用 menuconfig 命令打开 env 配置界面,在 RT-Thread online packages → IoT - internet of things 中选择 WebClient 软件包,操作界面如下图所示:

WebClient 软件包配置

详细配置介绍如下所示:

  1. RT-Thread online packages
  2. IoT - internet of things --->
  3. [*] WebClient: A HTTP/HTTPS Client for RT-Thread
  4. [ ] Enable support tls protocol
  5. [ ] Enable webclient GET/POST samples
  6. Version (latest) --->

Enable support tls protocol :开启对 HTTPS 支持;

Enable webclient GET/POST samples :添加示例代码;

Version :配置软件包版本号。

选择合适的配置项后,使用 pkgs —update 命令下载软件包并更新用户配置。

使用流程

使用 WebClient 软件包发送 GET/POST 请求一般需要完成如下基本流程:

  • 创建客户端会话结构体
  1. struct webclient_header
  2. {
  3. char *buffer; //添加或者获取的头部数据
  4. size_t length; //存放当前头部数据长度
  5.  
  6. size_t size; //存放最大支持的头部数据长度
  7. };
  8.  
  9. struct webclient_session
  10. {
  11. struct webclient_header *header; //保存头部信息结构体
  12. int socket; //当前连接套接字
  13. int resp_status; //响应状态码
  14.  
  15. char *host; //连接服务器地址
  16. char *req_url; //连接的请求地址
  17.  
  18. int chunk_sz; //chunk 模式下一块数据大小
  19. int chunk_offset; //chunk 模式剩余数据大小
  20.  
  21. int content_length; //当前接收数据长度(非 chunk 模式)
  22. size_t content_remainder; //当前剩余接收数据长度
  23.  
  24. #ifdef WEBCLIENT_USING_TLS
  25. MbedTLSSession *tls_session; // HTTPS 协议相关会话结构体
  26. #endif
  27. };

webclient_session 结构体用于存放当前建立的 HTTP 连接的部分信息,可用与 HTTP 数据交互整个流程。建立 HTTP 连接前需要创建并初始化该结构体,创建的方式示例如下:

  1. struct webclient_session *session = RT_NULL;
  2.  
  3. /* create webclient session and set header response size */
  4. session = webclient_session_create(1024);
  5. if (session == RT_NULL)
  6. {
  7. ret = -RT_ENOMEM;
  8. goto __exit;
  9. }
  • 拼接头部数据
    WebClient 软件包提供两种请求头部发送方式:

  • 默认头部数据

如果要使用默认的头部信息,则不需要拼接任何头部数据,可直接调用 GET 发送命令。默认头部数据一般只用于 GET 请求。

  • 自定义头部数据

自定义头部数据使用 webclient_header_fields_add 函数添加头部信息,添加的头部信息位于客户端会话结构体中,在发送 GET/POST 请求时发送。

添加示例代码如下:

  1. /* 拼接头部信息 */
  2. webclient_header_fields_add(session, "Content-Length: %d\r\n", strlen(post_data));
  3.  
  4. webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n");
  • 发送 GET/POST 请求
    头部信息添加完成之后,就可以调用 webclient_get 函数或者 webclient_post 函数发送 GET/POST 请求命令了,函数中主要操作如下:

  • 通过传入的 URI 获取信息,建立 TCP 连接;

  • 发送默认或者拼接的头部信息;

  • 接收并解析响应数据的头部信息;

  • 返回错误或者响应状态码。

发送 GET 请求示例代码如下:

  1. int resp_status = 0;
  2.  
  3. /* send GET request by default header */
  4. if ((resp_status = webclient_get(session, URI)) != 200)
  5. {
  6. LOG_E("webclient GET request failed, response(%d) error.", resp_status);
  7. ret = -RT_ERROR;
  8. goto __exit;
  9. }
  • 接收响应的数据
    发送 GET/POST 请求之后,可以使用 webclient_read 函数接收响应的实际数据。因为响应的实际数据可能比较长,所以往往我们需要循环接收响应数据,指导数据接收完毕。

如下所示为循环接收并打印响应数据方式:

  1. int content_pos = 0;
  2. /* 获取接收的响应数据长度 */
  3. int content_length = webclient_content_length_get(session);
  4.  
  5. /* 循环接收响应数据直到数据接收完毕 */
  6. do
  7. {
  8. bytes_read = webclient_read(session, buffer, 1024);
  9. if (bytes_read <= 0)
  10. {
  11. break;
  12. }
  13.  
  14. /* 打印响应数据 */
  15. for (index = 0; index < bytes_read; index++)
  16. {
  17. rt_kprintf("%c", buffer[index]);
  18. }
  19.  
  20. content_pos += bytes_read;
  21. } while (content_pos < content_length);
  • 关闭并释放客户端会话结构体
    请求发送并接收完成之后,需要使用 webclient_close 函数关闭并释放客户端会话结构体,完成整个 HTTP 数据交互流程。

使用方式如下:

  1. if (session)
  2. {
  3. webclient_close(session);
  4. }

使用方式

WenClient 软件包对于 GET/POST 请求,分别提供了几种不同的使用方式,用于不同的情况。

GET 请求方式

  • 使用默认头部发送 GET 请求
  1. struct webclient_session *session = NULL;
  2.  
  3. session = webclient_create(1024);
  4.  
  5. if(webclient_get(session, URI) != 200)
  6. {
  7. LOG_E("error!");
  8. }
  9.  
  10. while(1)
  11. {
  12. webclient_read(session, buffer, bfsz);
  13. ...
  14. }
  15.  
  16. webclient_close(session);
  • 使用自定义头部发送 GET 请求
  1. struct webclient_session *session = NULL;
  2.  
  3. session = webclient_create(1024);
  4.  
  5. webclient_header_fields_add(session, "User-Agent: RT-Thread HTTP Agent\r\n");
  6.  
  7. if(webclient_get(session, URI) != 200)
  8. {
  9. LOG_E("error!");
  10. }
  11.  
  12. while(1)
  13. {
  14. webclient_read(session, buffer, bfsz);
  15. ...
  16. }
  17.  
  18. webclient_close(session);
  • 发送获取部分数据的 GET 请求(多用于断点续传)
  1. struct webclient_session *session = NULL;
  2.  
  3. session = webclient_create(1024);
  4.  
  5. if(webclient_get_position(URI, 100) != 206)
  6. {
  7. LOG_E("error!");
  8. }
  9.  
  10. while(1)
  11. {
  12. webclient_read(session, buffer, bfsz);
  13. ...
  14. }
  15.  
  16. webclient_close(session);
  • 使用 webclient_response 接收 GET 数据

多用于接收数据长度较小的 GET 请求。

  1. struct webclient_session *session = NULL;
  2. char *result;
  3.  
  4. session = webclient_create(1024);
  5.  
  6. if(webclient_get(session, URI) != 200)
  7. {
  8. LOG_E("error!");
  9. }
  10.  
  11. webclient_response(session, &result);
  12.  
  13. web_free(result);
  14. webclient_close(session);
  • 使用 webclient_request 函数发送并接收 GET 请求

多用于接收数据长度较小,且头部信息已经拼接给出的 GET 请求。

  1. char *result;
  2.  
  3. webclient_request(URI, header, NULL, &result);
  4.  
  5. web_free(result);

POST 请求方式

  • 分段数据 POST 请求

多用于上传数据量较大的 POST 请求,如:上传文件到服务器。

  1. struct webclient_session *session = NULL;
  2.  
  3. session = webclient_create(1024);
  4.  
  5. /* 拼接必要的头部信息 */
  6. webclient_header_fields_add(session, "Content-Length: %d\r\n", post_data_sz);
  7. webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n");
  8.  
  9. /* 分段数据上传 webclient_post 第三个传输上传数据为 NULL,改为下面循环上传数据*/
  10. if( webclient_post(session, URI, NULL) != 200)
  11. {
  12. LOG_E("error!");
  13. }
  14.  
  15. while(1)
  16. {
  17. webclient_write(session, post_data, 1024);
  18. ...
  19. }
  20.  
  21. if( webclient_handle_response(session) != 200)
  22. {
  23. LOG_E("error!");
  24. }
  25.  
  26. webclient_close(session);
  • 整段数据 POST 请求

多用于上传数据量较小的 POST 请求。

  1. char *post_data = "abcdefg";
  2.  
  3. session = webclient_create(1024);
  4.  
  5. /* 拼接必要的头部信息 */
  6. webclient_header_fields_add(session, "Content-Length: %d\r\n", strlen(post_data));
  7. webclient_header_fields_add(session, "Content-Type: application/octet-stream\r\n");
  8.  
  9. if(webclient_post(session, URI, post_data) != 200);
  10. {
  11. LOG_E("error!");
  12. }
  13. webclient_close(session);
  • 使用 webclient_request 函数发送 POST 请求

多用于上传文件较小且头头部信息已经拼接给出的 POST 请求。

  1. char *post_data = "abcdefg";
  2. char *header = "xxx";
  3.  
  4. webclient_request(URI, header, post_data, NULL);

常见问题

HTTPS 地址不支持

  1. [E/WEB]not support https connect, please enable webclient https configure!
  • 原因:使用 HTTPS 地址但是没有开启 HTTPS 支持。

  • 解决方法:在 WebClient 软件包 menuconfig 配置选项中开启 Enable support tls protocol 选项支持。

头部数据长度超出

  1. [E/WEB]not enough header buffer size(xxx)!
  • 原因:添加的头部数据长度超过了最大支持的头部数据长度。

  • 解决方法:在创建客户端会话结构体的时候,增大传入的最大支持的头部数据长度。

原文: https://www.rt-thread.org/document/site/submodules/webclient/docs/user-guide/