欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何搭建http的webserver服務器

 更新時間:2024年08月22日 12:11:02   作者:逐夢,無懼!  
最近在使用ESP32搭建web服務器測試,發(fā)現(xiàn)esp32搭建這類開發(fā)環(huán)境還是比較方便的,下面介紹如何使用ESP32提供的API來搭建我們的http web,感興趣的朋友一起看看吧

最近在使用ESP32搭建web服務器測試,發(fā)現(xiàn)esp32搭建這類開發(fā)環(huán)境還是比較方便的。具體的http協(xié)議這里就不再贅述,我們主要說一下如何使用ESP32提供的API來搭建我們的http web。

一、web服務器搭建過程

1、配置web服務器

ESP-IDF中,Web服務器使用httpd組件實現(xiàn)。我們需要先創(chuàng)建httpd_config_t結構體,指定服務器的端口、最大并發(fā)連接數(shù)、URI匹配處理器等選項。然后,我們通過調用httpd_start函數(shù)來啟動Web服務器。(使用默認的配置就可以,包括端口號都已經(jīng)默認配置好了)

httpd_config_t config = HTTPD_DEFAULT_CONFIG();
httpd_handle_t server = NULL;
// 設置服務器端口為80
config.server_port = 80;
// 創(chuàng)建HTTP服務器句柄
if (httpd_start(&server, &config) != ESP_OK) {
    printf("Error starting server!\n");
    return;
}
 

2、 注冊 URI處理器

在Web服務器啟動后,我們需要為不同的URI注冊處理器函數(shù)。當Web服務器接收到請求時,會根據(jù)請求的URI選擇相應的處理器函數(shù)進行處理。在ESP-IDF中,我們可以使用httpd_register_uri_handler函數(shù)注冊URI處理器。該函數(shù)的原型如下

esp_err_t httpd_register_uri_handler(httpd_handle_t hd, const httpd_uri_t *uri)

其中,hd參數(shù)為HTTP服務器句柄;uri參數(shù)為包含URI路徑、HTTP方法、處理函數(shù)等信息的結構體指針。例如:

static const httpd_uri_t echo = {
    .uri       = "/",
    .method    = HTTP_POST,
    .handler   = echo_post_handler,
    .user_ctx  = NULL
};
static esp_err_t echo_post_handler(httpd_req_t *req)
{
    char buf[100];
    // char ssid[10];
    // char pswd[10];
    int ret, remaining = req->content_len;
    while (remaining > 0) {
        /* Read the data for the request */
        if ((ret = httpd_req_recv(req, buf,
                        MIN(remaining, sizeof(buf)))) <= 0) {
            if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
                /* Retry receiving if timeout occurred */
                continue;
            }
            return ESP_FAIL;
        }
        /* Send back the same data */
        httpd_resp_send_chunk(req, buf, ret);
        remaining -= ret;
        esp_err_t e = httpd_query_key_value(buf,"ssid",wifi_name,sizeof(wifi_name));
        if(e == ESP_OK) {
            printf("ssid = %s\r\n",wifi_name);
        }
        else {
            printf("error = %d\r\n",e);
        }
        e = httpd_query_key_value(buf,"password",wifi_password,sizeof(wifi_password));
        if(e == ESP_OK) {
            printf("pswd = %s\r\n",wifi_password);
        }
        else {
            printf("error = %d\r\n",e);
        }
        /* Log data received */
        ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
        ESP_LOGI(TAG, "%.*s", ret, buf);
        ESP_LOGI(TAG, "====================================");
    }
    // End response
    httpd_resp_send_chunk(req, NULL, 0);
    if(strcmp(wifi_name ,"\0")!=0 && strcmp(wifi_password,"\0")!=0)
    {
        xSemaphoreGive(ap_sem);
        ESP_LOGI(TAG, "set wifi name and password successfully! goto station mode");
    }
    return ESP_OK;
}

html的網(wǎng)頁如下:這個網(wǎng)頁包含了按鈕的定義,以及發(fā)送json格式的數(shù)據(jù)。

最后送json數(shù)據(jù)的時候,要用JSON.stringify方法格式化data,否則esp32解析json會報錯,此處一定要注意?。?!
整體html界面非常簡單,沒有基礎的也很容易讀懂,里面寫了一個js函數(shù),該函數(shù)是在點擊按鈕的時候觸發(fā),功能主要是讀取文本框輸入的數(shù)據(jù),將數(shù)據(jù)封裝為json格式,然后post發(fā)送數(shù)據(jù),xhttp.open(“POST”, “/wifi_data”, true);中的url “/wifi_data”和esp32服務端中的定義要一致,否則是無法成功的。

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <title>Web server system</title>
</head>
<table class="fixed" border="5">
    <col width="1000px" /><col width="500px" />
    <tr><td>
        <h2 style=" text-align:center;"> **** Web Server ***</h2>
        <h3>wifi 密碼配置</h3>
    <div>
        <label for="name">wifi名稱</label>
        <input type="text" id="wifi" name="car_name" placeholder="ssid">
        <br>
        <label for="type">密碼</label>
        <input type="text" id="code" name="car_type" placeholder="password">
        <br>
        <button id ="send_WIFI" type="button" onclick="send_wifi()">提交</button>
    </div>
    </td><td>
        <table border="10">
            <tr>
                <td>
                    <label for="newfile">Upload a file</label>
                </td>
                <td colspan="2">
                    <input id="newfile" type="file" onchange="setpath()" style="width:100%;">
                </td>
            </tr>
            <tr>
                <td>
                    <label for="filepath">Set path on server</label>
                </td>
                <td>
                    <input id="filepath" type="text" style="width:100%;">
                </td>
                <td>
                    <button id="upload" type="button" onclick="upload()">Upload</button>
                </td>
            </tr>
        </table>
    </td></tr>
</table>
<script>
function setpath() {
    var default_path = document.getElementById("newfile").files[0].name;
    document.getElementById("filepath").value = default_path;
}
function upload() {
    var filePath = document.getElementById("filepath").value;
    var upload_path = "/upload/" + filePath;
    var fileInput = document.getElementById("newfile").files;
    /* Max size of an individual file. Make sure this
     * value is same as that set in file_server.c */
    var MAX_FILE_SIZE = 200*1024;
    var MAX_FILE_SIZE_STR = "200KB";
    if (fileInput.length == 0) {
        alert("No file selected!");
    } else if (filePath.length == 0) {
        alert("File path on server is not set!");
    } else if (filePath.indexOf(' ') >= 0) {
        alert("File path on server cannot have spaces!");
    } else if (filePath[filePath.length-1] == '/') {
        alert("File name not specified after path!");
    } else if (fileInput[0].size > 200*1024) {
        alert("File size must be less than 200KB!");
    } else {
        document.getElementById("newfile").disabled = true;
        document.getElementById("filepath").disabled = true;
        document.getElementById("upload").disabled = true;
        var file = fileInput[0];
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState == 4) {
                if (xhttp.status == 200) {
                    document.open();
                    document.write(xhttp.responseText);
                    document.close();
                } else if (xhttp.status == 0) {
                    alert("Server closed the connection abruptly!");
                    location.reload()
                } else {
                    alert(xhttp.status + " Error!\n" + xhttp.responseText);
                    location.reload()
                }
            }
        };
        xhttp.open("POST", upload_path, true);
        xhttp.send(file);
    }
}
function send_wifi() {
    var input_ssid = document.getElementById("wifi").value;
    var input_code = document.getElementById("code").value;
    var xhttp = new XMLHttpRequest();
        xhttp.open("POST", "/wifi_data", true);
        xhttp.onreadystatechange = function() {
            if (xhttp.readyState == 4) {
                if (xhttp.status == 200) {
                    console.log(xhttp.responseText);
                } else if (xhttp.status == 0) {
                    alert("Server closed the connection abruptly!");
                    location.reload()
                } else {
                    alert(xhttp.status + " Error!\n" + xhttp.responseText);
                    location.reload()
                }
            }
        };
    var data = {
        "wifi_name":input_ssid,
        "wifi_code":input_code
    }
        xhttp.send(JSON.stringify(data));
}
</script>
static esp_err_t html_default_get_handler(httpd_req_t *req)
{
    // /* Send HTML file header */
    // httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
    /* Get handle to embedded file upload script */
    extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
    extern const unsigned char upload_script_end[] asm("_binary_upload_script_html_end");
    const size_t upload_script_size = (upload_script_end - upload_script_start);
    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);
    /* Send remaining chunk of HTML file to complete it */
    httpd_resp_sendstr_chunk(req, "</body></html>");
    /* Send empty chunk to signal HTTP response completion */
    httpd_resp_sendstr_chunk(req, NULL);
    return ESP_OK;
}
    httpd_uri_t html_default = {
        .uri = "/", // Match all URIs of type /path/to/file
        .method = HTTP_GET,
        .handler = html_default_get_handler,
        .user_ctx = "html" // Pass server data as context
    };
    httpd_register_uri_handler(server, &html_default);

這里要特別注意:

1)、.uri = "/",這個表示當你打開網(wǎng)頁的IP地址后第一個要顯示的頁面,也就是要放到根目錄下("/"也就是根目錄)。

2)、ESP32可以直接將html的網(wǎng)頁編譯進來不需要轉為數(shù)組,但在CMakeList.txt文件中需要EMBED_FILES upload_script.html這樣的形式引入網(wǎng)頁文件。這個html編譯出出來的文本文件怎么使用呢。wifi.html編譯出來一般名稱是默認的_binary_名稱_類型_start。這個指針代編譯出來文件的起始地址。_binary_名稱_類型_end,代表結束地址。wifi.html的引用方式如下。通過以下的方式就可以獲得html這個大數(shù)組。

    extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");
    extern const unsigned char upload_script_end[] asm("_binary_upload_script_html_end");
    const size_t upload_script_size = (upload_script_end - upload_script_start);
    /* Add file upload form and script which on execution sends a POST request to /upload */
    httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);

3、實現(xiàn)URI處理函數(shù)

在注冊URI處理器后,我們需要實現(xiàn)對應的處理器函數(shù)。URI處理器函數(shù)的原型為:

typedef esp_err_t (*httpd_uri_func_t)(httpd_req_t *req);
 

如上面示例中的:

static esp_err_t html_default_get_handler(httpd_req_t *req)

4、處理HTTP請求

在URI處理器函數(shù)中,我們可以通過HTTP請求信息結構體指針httpd_req_t獲取HTTP請求的各種參數(shù)和數(shù)據(jù)。以下是一些常用的HTTP請求處理函數(shù):

httpd_req_get_hdr_value_str:獲取HTTP請求頭中指定字段的值(字符串格式)
httpd_req_get_url_query_str:獲取HTTP請求URL中的查詢參數(shù)(字符串格式)
httpd_query_key_value:解析HTTP請求URL中的查詢參數(shù),獲取指定參數(shù)名的值(字符串格式)
httpd_req_recv:從HTTP請求接收數(shù)據(jù)
httpd_req_send:發(fā)送HTTP響應數(shù)據(jù)
httpd_resp_set_type:設置HTTP響應內容的MIME類型
httpd_resp_send_chunk:分塊發(fā)送HTTP響應數(shù)據(jù)。
例如,以下是一個URI處理器函數(shù)的示例,用于處理/echo路徑的POST請求:

static esp_err_t echo_post_handler(httpd_req_t *req)
{
    char buf[1024];
    int ret, remaining = req->content_len;
    // 從HTTP請求中接收數(shù)據(jù)
    while (remaining > 0) {
        ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
        if (ret <= 0) {
            if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
                // 處理超時
                httpd_resp_send_408(req);
            }
            return ESP_FAIL;
        }
        // 處理接收到的數(shù)據(jù)
        // ...
        remaining -= ret;
    }
    // 發(fā)送HTTP響應
    httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
    httpd_resp_send(req, "Received data: ", -1);
    httpd_resp_send_chunk(req, buf, req->content_len);
    httpd_resp_send_chunk(req, NULL, 0);
    return ESP_OK;
}
 

5、 發(fā)送響應

在URI處理函數(shù)中,可以使用httpd_resp_send()函數(shù)將響應發(fā)送回客戶端。該函數(shù)需要傳入一個httpd_req_t結構體作為參數(shù),該結構體表示HTTP請求和響應。

例如,在上面的hello_get_handler處理函數(shù)中,可以使用httpd_resp_send()函數(shù)將“Hello, World!”字符串作為響應發(fā)送回客戶端:

static esp_err_t hello_get_handler(httpd_req_t *req)
{
    const char* resp_str = "Hello, World!";
    httpd_resp_send(req, resp_str, strlen(resp_str));
    return ESP_OK;
}

二、主要使用API的說明

1. httpd_register_uri_handler
用于將HTTP請求的URI路由到處理程序。這個函數(shù)接收兩個參數(shù):httpd_handle_t類型的HTTP服務器句柄和httpd_uri_t類型的URI配置。

2. httpd_handle_t
httpd_handle_t是HTTP服務器的一個句柄,它是通過httpd_start函數(shù)創(chuàng)建的。而httpd_uri_t則定義了HTTP請求的URI信息,包括URI路徑、HTTP請求方法和處理函數(shù)等。

3. httpd_query_key_value獲取變量值
httpd_query_key_value 用于從查詢字符串中獲取指定鍵的值。查詢字符串是指URL中?后面的部分,包含多個鍵值對,每個鍵值對之間使用&分隔。例如,對于以下URL:
http://192.168.1.1/path/to/handler?key1=value1&key2=value2
獲取其中的:
esp_err_t httpd_query_key_value(const char *query, const char *key, char *buf, size_t buf_len);

這是一個使用示例

char query_str[] = "key1=value1&key2=value2";
char key[] = "key1";
char value[16];
if (httpd_query_key_value(query_str, key, value, sizeof(value)) == ESP_OK) {
    printf("value=%s\n", value);
} else {
    printf("key not found\n");
}
 

4. 獲取get參數(shù)示例

下面定義的 handler 演示了如何從請求參數(shù)里解析 字符串param1和整型變量param2:

 esp_err_t index_handler(httpd_req_t *req)
{
     char* query_str = NULL;
     char param1_value[10] = {0};
     int param2_value=0;
     query_str = strstr(req->uri, "?");
     if(query_str!=NULL){
         query_str ++;
         httpd_query_key_value(query_str, "param1", param1_value, sizeof(param1_value));
         char param2_str[10] = {0};
         httpd_query_key_value(query_str, "param2", param2_str, sizeof(param2_str));
         param2_value = atoi(param2_str);
     }
     char resp_str[50] = {0};
     snprintf(resp_str, sizeof(resp_str), "param1=%s, param2=%d", param1_value, param2_value);
    httpd_resp_send(req, resp_str, strlen(resp_str));
    return ESP_OK;
}

5. 獲取post參數(shù)示例

下面的示例代碼中根據(jù)httpd_req_t的content_len來分配一個緩沖區(qū),并解析請求中的POST參數(shù):

 
 esp_err_t post_demo_handler(httpd_req_t *req)
{
    char post_string[64];
    int post_int=0;
    if (req->content_len > 0)
    {
        // 從請求體中讀取POST參數(shù)
        char *buf = malloc(req->content_len + 1);
        int ret = httpd_req_recv(req, buf, req->content_len);
        if (ret <= 0)
        {
            // 接收數(shù)據(jù)出錯
            free(buf);
            return ESP_FAIL;
        }
        buf[req->content_len] = '\0';
        // 解析POST參數(shù)
        char *param_str;
        param_str = strtok(buf, "&");
        while (param_str != NULL)
        {
            char *value_str = strchr(param_str, '=');
            if (value_str != NULL)
            {
                *value_str++ = '\0';
                if (strcmp(param_str, "post_string") == 0)
                {
                    strncpy(post_string, value_str, sizeof(post_string));
                }
                else if (strcmp(param_str, "post_int") == 0)
                {
                    post_int = atoi(value_str);
                }
            }
            param_str = strtok(NULL, "&");
        }
        free(buf);
    }
    // 將結果打印輸出
    printf("post_string=%s, post_int=%d\n", post_string, post_int);
    // 返回成功
    httpd_resp_send(req, NULL, 0);
    return ESP_OK;
}
 httpd_uri_t post_uri = {
         .uri = "/post",
         .method = HTTP_POST,
         .handler = post_demo_handler,
         .user_ctx = NULL
 };

到此這篇關于搭建http的webserver的服務器的文章就介紹到這了,更多相關http的webserver服務器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論