文章目录
参考资料:《计算机网络(第7版)-谢希仁》
1 统一资源定位符URL
1.1 URL的格式
统一资源定位符URL(Uniform Resource Locator) 是用来表示从互联网上得到的资源位置和访问这些资源的方法。URL实际上就是在互联网上资源的地址。显然, 互联网上的所有资源, 都有一个唯一确定的URL。这里所说的 “ 资源” 是指在互联网上可以被访问的任何对象, 包括文件目录、 文件、 文档、 图像、 声音等, 以及与互联网相连的任何形式的数据。
URL相当于一个文件名在网络范围的扩展。 因此, URL 是与互联网相连的机器上的任何可访问对象的一个指针。 由于访问不同对象所使用的协议不同, 所以URL还指出读取某个对象时所使用的协议。 URL的一般形式由以下四个部分组成:
<协议>://<主机>:<端口>/<路径>
- <协议>就是指使用什么协议来获取该万维网文档。 现在最常用的协议就是http(超文本传送协议HTTP),其次是ftp(文件传送协 议FTP)。
- <主机>就是指出这个万维网文档是在哪一台主机上,即该主机在互联网上的域名。
- <端口>就是指协议相对应的端口,如HTTP的默认端口号是80, 通常可省略。
- <路径>就是指在该主机下资源存放的位置。
1.2 使用HTTP协议的URL
对于万维网的网点的访问要使用HTTP协议。 HTTP协议 的URL 的一般形式是:
http://<主机>:<端口>/<路径>
HTTP的默认端口号是80, 通常可省略。 若再省略文件的〈路径〉项, 则URL就指向互联网上的某个主页(home page)。
例如:https://www.espressif.com/, 只显示主页内容
如果添加<路径>则可以链接该主机下各种资源
例如:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/get-started/index.html
这里是乐鑫编程指南页面的URL。注意:上面的URL中使用了指向文件的路径, 而文件名就是最后的index.html。 后缀html (有时可写为htm)表示这是一个用超文本标记语言HTML写出的文件。
2 超文本传送协议 HTTP
HTTP协议定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。
2.1 HTTP的报文结构
HTTP 有两类报文:
(1) 请求报文一一从客户向服务器发送请求报文, 见图6-12(a)。
(2) 响应报文一一从服务器到客户的回答, 见图6-12(b)。
由于HTTP是面向文本的(text-oriented), 因此在报文中的每一个字段都是 一些ASCII码串, 因而各个字段的长度都是不确定的。
HTTP 请求报文和响应报文都是由三个部分组成的。 可以看出, 这两种报文格式的区别就是开始行不同。
- 开始行, 用于区分是请求报文还是响应报文。 在请求报文中的开始行叫做请求行(Request-Line), 而在响应报文中的开始行叫做状态行(Status-Line)。 在开始行的三个字段之间都以空格分隔开, 最后的 “CR” 和 “LF” 分别代表 回车 和 换行。
- 首部行, 用来说明浏览器、 服务器或报文主体的一些信息。 首部可以有好几行, 但也可以不使用。在每一个首部行中都有首部字段名和它的值,每一行结束的地方都要有“回车”和“换行”,整个首部行结束时 ,还有一空行将首部行和后面的实体主体分开。
- 实体主体(entity body), 在请求报文中一般都不用这个字段, 而在响应报文中也可能没有这个字段。
2.1.1 HTTP请求报文
-
请求报文说明
请求报文的第一行 “请求行” 只有三个内容, 即方法, 请求资源的URL, 以及HTTP的版本。
请注意: 这里的名词 “ 方法 ” (method) 是面向对象技术中使用的专门名词。 所谓 “ 方法” 就是对所请求的对象进行的操作, 这些方法实际上也就是一些命令。 因此, 请求报文的类型是由它所采用的方法决定的。 这些常用的方法如下所示:
-
请求报文举例
下面是HTTP的请求报文的开始行〈即请求行)的格式。请注意,在GET后面有一个空格,接着是某个完整的URL,其后面又有个空格,最后是HTTP/1.1。例如,GET http://www.xyz.edu.cn/dir/index.htm HTTP/1.1
下面是一个完整的HTTP请求报文的例子:
在请求行使用了相对URL(即省略了主机的域名〉是因为下面的首部行(第2行〉给出了主机的域名。第3行是告诉服务器不使用持续连接,表示浏览器希望服务器在传送完所请求的对象后即关闭TCP连接。这个请求报文没有实体主体。
2.1.2 HTTP响应报文
再看一下HTTP响应报文的主要特点。
每一个请求报文发出后,都能收到一个响应报文。响应报文的第一行就是状态行。
状态行包括三项内容,即HTTP的版本,状态码,以及解释状态码的简单短语。
状态码(Status-Code)都是三位数字的,分为5大类,这5大类的状态码都是以不同的数字开头的。
1xx表示通知信息,如请求收到了或正在进行处理。
2xx表示成功,如接受或知道了。
3xx表示重定向,如要完成请求还必须采取进步的行动。
4xx表示客户的差错,如请求中有错误的语法或不能完成。
5xx表示服务器的差错,如服务器失效无法完成请求。
3 HTTP实验工具httpbin.org
httpbin这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等,且支持 GET、POST 等多种方法,对 web 开发和测试很有帮助。即你可以向他发送请求,然后他会按照指定的规则将你的请求返回(查看你所发送请求中的信息)。,网页如下图所示
官方网站:httpbin.org
开源地址:httpbin.org
常用接口列表:
4 工程测试
使用的工程为 esp_http_client
函数详细分析请参考:ESP HTTP Client
4.1 工程烧录
-
将esp_http_client复制到自己创建的app目录下,这一步的目的是不破坏官方的完整例程
-
进入配置菜单
idf.py menuconfig
,配置wifi
-
最后使用指令
idf.py -p COM11 flash monitor
编译烧录并打开串口助手
4.2 工程分析
- 该工程默认使用的测试工具也是httpbin.org
- 工程中进行了各种方法的测试,如url,host和path等
该工程里是全部一起测试,自己可以单独去测试,如仅留下http_rest_with_url();
函数,屏蔽其他函数
4.3 工程代码分析
- HTTP 配置参数
工程中都需要配置esp_http_client_config_t
,其具体配置如下/** * @brief HTTP configuration */ typedef struct { const char *url; /*统一资源定位符!< HTTP URL, the information on the URL is most important, it overrides the other fields below, if any */ const char *host; /*服务器域名或ip地址 !< Domain or IP as string */ int port; /*端口 http默认80 https 默认443!< Port to connect, default depend on esp_http_client_transport_t (80 or 443) */ const char *username; /*用户名,认证时使用!< Using for Http authentication */ const char *password; /*用户密码,认证时使用!< Using for Http authentication */ esp_http_client_auth_type_t auth_type; /*认证方式!< Http authentication type, see `esp_http_client_auth_type_t` */ const char *path; /*路径!< HTTP Path, if not set, default is `/` */ const char *query; /*请求参数!< HTTP query */ const char *cert_pem; /*证书!< SSL server certification, PEM format as string, if the client requires to verify server */ const char *client_cert_pem; /*!< SSL client certification, PEM format as string, if the server requires to verify client */ const char *client_key_pem; /*!< SSL client key, PEM format as string, if the server requires to verify client */ esp_http_client_method_t method; /*!< HTTP Method */ int timeout_ms; /*请求超时!< Network timeout in milliseconds */ bool disable_auto_redirect; /*!< Disable HTTP automatic redirects */ int max_redirection_count; /*!< Max redirection number, using default value if zero*/ http_event_handle_cb event_handler; /*!< HTTP Event Handle */ esp_http_client_transport_t transport_type; /*!< HTTP transport type, see `esp_http_client_transport_t` */ int buffer_size; /*!< HTTP receive buffer size */ int buffer_size_tx; /*!< HTTP transmit buffer size */ void *user_data; /*!< HTTP user_data context */ bool is_async; /*!< Set asynchronous mode, only supported with HTTPS for now */ bool use_global_ca_store; /*!< Use a global ca_store for all the connections in which this bool is set. */ bool skip_cert_common_name_check; /*!< Skip any validation of server certificate CN field */ } esp_http_client_config_t;
4.2.1 HTTP 实验之使用URL获取资源
-
方法(method)GET
static void http_rest_with_url(void) { char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; /** * NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters. * If host and path parameters are not set, query parameter will be ignored. In such cases, query parameter should be specified in URL. * * If URL as well as host and path parameters are specified, values of host and path will be considered. */ /*有些参数没有配置则会使用默认参数*/ esp_http_client_config_t config = { .url = "http://httpbin.org/get", .method = HTTP_METHOD_GET, .event_handler = _http_event_handler, .user_data = local_response_buffer, // Pass address of local buffer to get response }; esp_http_client_handle_t client = esp_http_client_init(&config); // GET esp_err_t err = esp_http_client_perform(client); if (err == ESP_OK) { ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d", esp_http_client_get_status_code(client), esp_http_client_get_content_length(client)); } else { ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); } // ESP_LOG_BUFFER_HEX(TAG, local_response_buffer, strlen(local_response_buffer)); /*以十六进制形式输凿/ ESP_LOGI(TAG, "recv data ---2 = %d %s\r\n", strlen(local_response_buffer), local_response_buffer); //打印数据 esp_http_client_cleanup(client); }
编译程序,烧录到ESP32开发板,并通过串口打印,数据如下:
-
方法(method)POST
static void http_rest_with_url(void) { char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; /** * NOTE: All the configuration parameters for http_client must be spefied either in URL or as host and path parameters. * If host and path parameters are not set, query parameter will be ignored. In such cases, query parameter should be specified in URL. * * If URL as well as host and path parameters are specified, values of host and path will be considered. */ /*有些参数没有配置则会使用默认参数*/ esp_http_client_config_t config = { .url = "http://httpbin.org/get", .method = HTTP_METHOD_GET, .event_handler = _http_event_handler, .user_data = local_response_buffer, // Pass address of local buffer to get response }; esp_http_client_handle_t client = esp_http_client_init(&config); //POST //下面有些参数会被重新覆盖,如url、method const char *post_data = "{\"field1\":\"value1\"}"; esp_http_client_set_url(client, "http://httpbin.org/post"); esp_http_client_set_method(client, HTTP_METHOD_POST); esp_http_client_set_header(client, "Content-Type", "application/json"); esp_http_client_set_post_field(client, post_data, strlen(post_data)); err = esp_http_client_perform(client); if (err == ESP_OK) { ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d", esp_http_client_get_status_code(client), esp_http_client_get_content_length(client)); } else { ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err)); } ESP_LOGI(TAG, "POST recv len = %d ,data:\r\n %s ", strlen(local_response_buffer), local_response_buffer); //打印数据 esp_http_client_cleanup(client);
编译程序,烧录到ESP32开发板,并通过串口打印,数据如下:
4.2.2 HTTP 实验之使用host和path获取资源
使用“host和path”和使用“URL”获取的资源是一样的
-
方法(method)GET
static void http_rest_with_hostname_path(void) { char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; esp_http_client_config_t config = { .host = "httpbin.org", .path = "/get", .query = "ESP", //在url中添加请求参数 .transport_type = HTTP_TRANSPORT_OVER_TCP, .event_handler = _http_event_handler, .user_data = local_response_buffer, // Pass address of local buffer to get response }; esp_http_client_handle_t client = esp_http_client_init(&config); // GET esp_err_t err = esp_http_client_perform(client); if (err == ESP_OK) { ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d", esp_http_client_get_status_code(client), esp_http_client_get_content_length(client)); } else { ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); } ESP_LOGI(TAG, "GET recv len = %d ,data:\r\n %s ", strlen(local_response_buffer), local_response_buffer); //打印数据 esp_http_client_cleanup(client); }
编译程序,烧录到ESP32开发板,并通过串口打印,数据如下: