一.HTTP介绍

HTTP(超文本传输协议,Hypertext Transfer Protocol)是一种用于在互联网传输数据的协议,主要用于客户端与服务器之间的通信。它是Web的基础,使得浏览器能够请求网页和服务器能够返回网页内容。

  • 是用于从WWW服务器传输超文本到本地浏览器的传
    输协议
  • HTTP是客户端浏览器或其他程序与Web服务器之间的
    应用层通信协议
  • HTTP在TCP/IP网络模型中属于应用层,是基于TCP协议传输。

1.1 HTTP协议版本

  • HTTP/1.0
    发布日期:1996年
    特点:
    引入了请求和响应的头部,允许在请求中携带更多信息(如用户代理、内容类型等)。
    每个请求会建立一个新的TCP连接,效率较低。
    支持多种请求方法,如GET和POST。
  • HTTP/1.1
    发布日期:1999年
    特点:
    改进了连接管理,支持持久连接(keep-alive),允许在一个TCP连接上多次发送请求,提升性能。
    引入了更多的请求和响应头,例如Host头用于指定虚拟主机。
    增加了缓存控制的机制,支持分块传输编码和范围请求。
  • HTTP/2
    发布日期:2015年
    特点:
    使用二进制分帧,取代了文本格式,减少了传输数据的开销。
    支持多路复用,允许多个请求和响应在一个连接上并行处理,显著提高了页面加载速度。
    引入了头部压缩和服务器推送功能,使得web应用更加高效。

目前大部分采用的是HTTP1.1的协议版本

1.2 报文类型

  • GET:请求指定的页面信息,并返回实体主体。传递参数长度受限制,因为传递的参数是直接表示在地址栏中HEAD:HEAD跟GET相似,不过服务端接收到HEAD请求时只返回响应头,不发送响应内容。请求参数通常以查询字符串的形式附加于请求的URL。

例如https://mail.163.com&name=aaa&pass=aaaa,这就是将请求数据附加在url里进行发送

  • POST:把传递的数据封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据,对数据量没有限制DELETE:删除某一个资源。
  • OPTIONS:用于获取当前URL所支持的方法。若请求成功,会在HTTP头中包含一个名为“Allow”的头,值是所支持的方法,如“GET,POST
  • PUT:PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区
    别,PUT通常指定了资源的存放位置,而POST则没有
  • TRACE:回显服务器收到的请求,主要用于测试或诊断。
  • CONNECT:CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器

1.3 请求报文格式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到,我们网页是作为一个客户端,当我向服务端发起请求后,服务端就会返回给我们一个个应答报文,而应答报文里的主体组成了我们所看到网页数据。

1.4 简单网页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
    <style>
        .hello-text {
            position: fixed;
            top: 10px;
            left: 10px;
            margin: 0;
            font-family: Arial, sans-serif;
            font-size: 20px;
            color: #333;
        }
    </style>
</head>
<body>
    <p class="hello-text">Hello World</p>
</body>
</html>

这就是一个最简单html网页,当我们打开这个html文件时可以看到网页界面,但这个网页界面并不具备http的协议。我们可以在esp32端创建一个http服务端,当我们使用浏览器对其发起请求时,服务端就会将html页面映射到网页上。

二. esp32http服务端器

在esp32端上创建一个http服务器主要有以下几个步骤

  • 1.配置服务器参数,如端口号等
  • 2.开启服务器
  • 3.创建get请求回调函数,每次客户端访问时,将html界面发送给客户端
  • 4.创建post请求回调函数
#include "http_server.h"

static esp_err_t http_req_handler(httpd_req_t *req);
esp_err_t http_post_handler(httpd_req_t *req);

static httpd_handle_t server = NULL;
static const char *TAG = "HTTP_SRV";

/* URI配置表 */
static const httpd_uri_t uri_get = {
    .uri = "/",
    .method = HTTP_GET,
    .handler = http_req_handler,
    .user_ctx = NULL
};

/* POST/uri 的 URI 处理结构 */
httpd_uri_t uri_post = {
    .uri      = "/api/post",
    .method   = HTTP_POST,
    .handler  = http_post_handler,
    .user_ctx = NULL
};

static const char html_page[] = 
    // HTML基础结构
    "<!DOCTYPE html>" 
    "<html>"
    "<head>"
        "<title>Hello</title>"  
    "</head>"
    "<body>"
        // UI元素
        "<h1>Hello World</h1>" 
        "<p>Hello World</p>"
        "<button type=\"button\" onclick=\"postbutt()\">Post</button>"

        // JavaScript逻辑
        "<script type=\"text/javascript\">"   
            "function postbutt() {" 
                "var xmlhttp = new XMLHttpRequest();"
                "xmlhttp.open(\"POST\", \"/api/post\", true);" // 重要:使用绝对路径[^1]
                "xmlhttp.setRequestHeader("
                    "\"Content-type\", " 
                    "\"application/x-www-form-urlencoded\""
                ");" 
                "xmlhttp.send(\"data=post+test\");" // 特殊符号需编码验证
            "}"
        "</script>"
    "</body>"
    "</html>";


static esp_err_t http_req_handler(httpd_req_t *req)
{
    // 设置HTTP响应头
    httpd_resp_set_type(req, "text/html");
    
    // 发送完整HTML内容
    return httpd_resp_send(req, html_page, sizeof(html_page));
};

/* URI 处理函数,在客户端发起 POST/uri 请求时被调用 */
esp_err_t http_post_handler(httpd_req_t *req)
{
    /* 定义 HTTP POST 请求数据的目标缓存区
     * httpd_req_recv() 只接收 char* 数据,但也可以是
     * 任意二进制数据(需要类型转换)
     * 对于字符串数据,null 终止符会被省略,
     * content_len 会给出字符串的长度 */
    char content[100];

    /* 如果内容长度大于缓冲区则截断 */
   // size_t recv_size = MIN(req->content_len, sizeof(content));

    int ret = httpd_req_recv(req, content, req->content_len);
    if (ret <= 0) {  /* 返回 0 表示连接已关闭 */
        /* 检查是否超时 */
        if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
            /* 如果是超时,可以调用 httpd_req_recv() 重试
             * 简单起见,这里我们直接
             * 响应 HTTP 408(请求超时)错误给客户端 */
            httpd_resp_send_408(req);
        }
        /* 如果发生了错误,返回 ESP_FAIL 可以确保
         * 底层套接字被关闭 */
        return ESP_FAIL;
    }
    ESP_LOGI(TAG,"http_data:%s",content);
    /* 发送简单的响应数据包 */
    const char resp[] = "URI POST Response";
    httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}



/* HTTP服务启动 */
void start_webserver()
{
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 80;  // 设置默认HTTP端口

    if (httpd_start(&server, &config) == ESP_OK) {
        httpd_register_uri_handler(server, &uri_get);  // 注册GET请求处理
        httpd_register_uri_handler(server, &uri_post);  // 注册GET请求处理
        ESP_LOGI(TAG, "HTTP server started on port 80");
        lcd_printf(5,190,16,"http_server created ok,port:80");
    }
    else{
        lcd_printf(5,190,16,"http_server error");
    }
}


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐