国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

4·ESP32-C3入門教程——從本地控制走向云端控制(TCP/IP UDP篇)

這篇具有很好參考價值的文章主要介紹了4·ESP32-C3入門教程——從本地控制走向云端控制(TCP/IP UDP篇)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

? ? ? ? 距離實現(xiàn)一個完整的物聯(lián)網(wǎng)小應(yīng)用只差最后一步了,今天聊聊怎么樣在手機上對ESP32芯片發(fā)送指令和接收數(shù)據(jù),并借助ESP官方的接口——rainmaker,來實現(xiàn)遠程控制和通信。我們也借由此進入智能家居時代1.0(部分物聯(lián)網(wǎng)概念可以看看【序】在23年談物聯(lián)網(wǎng))

? ? ? ?

目錄

level 1:通過socket廣播收發(fā)實現(xiàn)本地控制

建立TCP SCOKET CLIENT通信

建立TCP SCOKET SEVER通信

小結(jié)

level 2:更廣泛的傳輸--UDP通信 & 通過遠程控制實現(xiàn)點燈

總結(jié)


????????雖然在上一篇中我們已經(jīng)學(xué)習(xí)到了如何讓ESP32-C3通過WiFi連接互聯(lián)網(wǎng),以及如何通過UDP廣播的方式通過手機上的esp touch為ESP32輕松配置網(wǎng)絡(luò)(鏈接指路→ESP32 從scan到smart config 講透WIFI配置)但我們?nèi)匀恍枰M一步,如果把互聯(lián)網(wǎng)比作是不同端口之間的路線的話,處理器如何判斷哪些數(shù)據(jù)是需要的,哪些數(shù)據(jù)是不需要的呢?這是我們今天所想要解決的問題。

? ? ? ? 所以這里我們就需要更進一步引入?yún)f(xié)議的概念。一般情況下基于WiFi和以太網(wǎng)的設(shè)備都會原生運行我們比較熟知的互聯(lián)網(wǎng)TCP/IP協(xié)議棧,通過它,我們可以大大降低數(shù)據(jù)本身協(xié)議的適配和開發(fā)難度(but 雖然降低了,對于入門來說仍然有很多東西要學(xué))

????????TCP即傳輸控制協(xié)議,是一種面向連接的、可靠的、基于字節(jié)流的通信協(xié)議,分為服務(wù)器和客戶端。服務(wù)器端先初始化Socket,然后與端口綁定(bind),對端口進行監(jiān)聽(listen),調(diào)用accept阻塞,等待客戶端連接。在這時如果有個客戶端初始化一個Socket,然后連接服務(wù)器(connect),如果連接成功,這時客戶端與服務(wù)器端的連接就建立了。客戶端發(fā)送數(shù)據(jù)請求,服務(wù)器端接收請求并處理請求,然后把回應(yīng)數(shù)據(jù)發(fā)送給客戶端,客戶端讀取數(shù)據(jù),最后關(guān)閉連接,一次交互結(jié)束。

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)
TCP通信的框圖

level 1:通過socket廣播收發(fā)實現(xiàn)本地控制

? ? ? ? 開始廣播收發(fā)之前,我們需要下載一個網(wǎng)絡(luò)調(diào)試工具(NetAssist)的軟件。可以幫助我們調(diào)節(jié)端口的位置地址以及相關(guān)的參數(shù)的,我們可以通過它來進行內(nèi)容的收發(fā)。下載鏈接指路(鏈接源于網(wǎng)絡(luò)):NetAssist網(wǎng)絡(luò)調(diào)試助手.exe

? ? ? ? ?安裝完成之后打開會看到如下的界面:

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

????????

????????其實乍一看SOCKET概念的時候,我還是有一點懵的,因為之前沒有做過網(wǎng)絡(luò)通信相關(guān)的實驗,花了好一陣子才開始理清整體的結(jié)構(gòu)和概念,上面的圖一定要結(jié)合代碼多看幾遍(當(dāng)然,我下面的注釋也會按照層級來詳細解釋)

????????首先要解釋一下這個client是什么,在上面TCP通信的框圖里面,我們看到了左半部分作為客戶端,右半部分作為服務(wù)端;connect之后,客戶端可以直接提交內(nèi)容和接受信息,但服務(wù)端在收發(fā)信息之前,需要bind listen accept確立狀態(tài)。

? ? ? ? 所以我們先從左半邊相對簡單的的客戶端去分析~

建立TCP SCOKET CLIENT通信

? ? ? ?首先我們從整體上對整個代碼的概念進行認識,因為我們esp是client模式,所以要先去看電腦端的 網(wǎng)絡(luò)調(diào)試助手選擇的ip和端口,并且填入到最上面這里#define,不然則會無法配對。關(guān)于函數(shù)部分的詳細原理會在后面的小結(jié)部分梳理,先從整體上對各個功能模塊認知,建立宏觀的基礎(chǔ)概念更有利于理解(個人看法)。

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

源代碼如下:

#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "addr_from_stdin.h"
#include "lwip/err.h"
#include "lwip/sockets.h"



#define HOST_IP_ADDR    "192.168.0.133"  
#define PORT            3333

static const char *TAG = "example";
static const char *payload = "message from computer";

static void tcp_client_task(void *pvParameters)
{
    char rx_buffer[128];
    char host_ip[] = HOST_IP_ADDR;
    int addr_family = 0;
    int ip_protocol = 0;

    while (1)   //大while(1)
    {
        struct sockaddr_in dest_addr;
        dest_addr.sin_addr.s_addr = inet_addr(host_ip);
        dest_addr.sin_family = AF_INET;     //調(diào)用了另一個文件中的 #define AF_INET 2
        dest_addr.sin_port = htons(PORT);   //port 上面咱們定義過啦
        addr_family = AF_INET;              //(同上)
        ip_protocol = IPPROTO_IP;           //#define IPPROTO_IP 0;


        int sock =  socket(addr_family, SOCK_STREAM, ip_protocol);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Socket created, connecting to %s:%d", host_ip, PORT);

        int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
        if (err != 0) {
            ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
            break;
        }
        ESP_LOGI(TAG, "Successfully connected");

        while (1) //大while(1)里面的while(1)
        {
            int err = send(sock, payload, strlen(payload), 0);
            if (err < 0) {
                ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
                break;
            }

            int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
            // Error occurred during receiving
            if (len < 0) {
                ESP_LOGE(TAG, "recv failed: errno %d", errno);
                break;
            }
            // Data received
            else {
                rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                ESP_LOGI(TAG, "Received %d bytes from %s:", len, host_ip);
                ESP_LOGI(TAG, "%s", rx_buffer);
            }

            vTaskDelay(2000 / portTICK_PERIOD_MS);
        }

        if (sock != -1) {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(sock, 0);
            close(sock);
        }
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(example_connect());

    xTaskCreate(tcp_client_task, "tcp_client", 4096, NULL, 5, NULL);
}

? ? ? ? 因為調(diào)用了其他文件夾的文件,所以需要修改一下頂層的cmakelist(注意,不是main文件夾里面的),這樣可以鏈接到通信所需要用到的兩個頭文件。

cmake_minimum_required(VERSION 3.5)  
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(mqtt_tcp)

建立TCP SCOKET SEVER通信

? ? ? ? 作為SERVER端,其實代碼中需要考慮的東西是更多的,不能僅僅看作只增加了bind()、listen()和accept();不過如果client部分有沒看懂的部分也沒關(guān)系,可能學(xué)完sever部分會有新的觀念,還是老規(guī)矩,我們先從整體的角度出發(fā):

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

源代碼如下:

#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>


#define PORT                        3333
#define KEEPALIVE_IDLE              5
#define KEEPALIVE_INTERVAL          5
#define KEEPALIVE_COUNT             3

static const char *TAG = "tcp server";

void wifi_get_ip(void)
{
    tcpip_adapter_ip_info_t ipInfo;
    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ipInfo);
    ESP_LOGI(TAG, "wifi_get_ip ip=%s", ip4addr_ntoa(&(ipInfo.ip.addr)));
}

static void do_retransmit(void *pvParameters)
{
    int sock = (int)pvParameters;
    int len;
    char rx_buffer[128];

    ESP_LOGI(TAG, "do_retransmit(%d)", sock);
    while(true)
    {
        len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
        if (len < 0) {
            ESP_LOGE(TAG, "Socket(%d) Error occurred during receiving: errno %d", sock, errno);
            shutdown(sock, 0);
            close(sock);
            vTaskDelete(NULL);
        } 
        
        else if (len == 0) {
            ESP_LOGW(TAG, "Socket(%d) Connection closed", sock);
        }
        
        else {
            rx_buffer[len] = 0; // 空中止接收到任何內(nèi)容都視為字符串
            ESP_LOGI(TAG, "Socket(%d) Received %d bytes: %s", sock, len, rx_buffer);

            // send() 可以返回定義長度更短的字符,所以有一點裕度更好(個人翻譯的,不一定準(zhǔn)確qwq)
            int to_write = len;
            while (to_write > 0) 
            {
                int written = send(sock, rx_buffer + (len - to_write), to_write, 0);
                if (written < 0) {
                    ESP_LOGE(TAG, "Socket(%d) Error occurred during sending: errno %d", sock, errno);
                }
                to_write -= written;
            }
        }
    }
}

static void tcp_server_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family = (int)pvParameters;
    int ip_protocol = 0;
    int keepAlive = 1;
    int keepIdle = KEEPALIVE_IDLE;
    int keepInterval = KEEPALIVE_INTERVAL;
    int keepCount = KEEPALIVE_COUNT;
    struct sockaddr_storage dest_addr;

    wifi_get_ip();
    if (addr_family == AF_INET) {
        struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
        dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY);
        dest_addr_ip4->sin_family = AF_INET;
        dest_addr_ip4->sin_port = htons(PORT);
        ip_protocol = IPPROTO_IP;
    }

    int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
    if (listen_sock < 0) {
        ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
        vTaskDelete(NULL);
        return;
    }
    int opt = 1;
    setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    ESP_LOGI(TAG, "Socket created");

    int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
    if (err != 0) {
        ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
        ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
        goto CLEAN_UP;
    }
    ESP_LOGI(TAG, "Socket bound, port %d", PORT);

    err = listen(listen_sock, 1);
    if (err != 0) {
        ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
        goto CLEAN_UP;
    }

    while (1) {
        ESP_LOGI(TAG, "Socket listening");
        struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
        socklen_t addr_len = sizeof(source_addr);
        int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
        if (sock < 0) {
            ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
            break;
        }

        // Set tcp keepalive option
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
        // Convert ip address to string
        if (source_addr.ss_family == PF_INET) {
            inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
        }
        ESP_LOGI(TAG, "Socket accepted ip address: %s | %d", addr_str, sock);

        // do_retransmit(sock);
        xTaskCreate(do_retransmit, "do_retransmit", 4096, (void*)sock, 6, NULL);
    }

CLEAN_UP:
    close(listen_sock);
    vTaskDelete(NULL);
}

void app_main(void)
{
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    example_connect();

    xTaskCreate(tcp_server_task, "tcp_server", 4096, (void*)AF_INET, 5, NULL);  
}

小結(jié)

整體梳理一下所用到的函數(shù)部分,其實不難看出幾乎每一個步驟都是圍繞著socket操作的。

socket創(chuàng)建

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

socket綁定

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

socket監(jiān)聽

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

socket連接

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

發(fā)送數(shù)據(jù)

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

接受數(shù)據(jù)

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

socket關(guān)閉

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

socket釋放

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

level 2:更廣泛的傳輸--UDP通信 & 通過遠程控制實現(xiàn)點燈

????????UDP?是?User?Datagram?Protocol?的簡稱,?中文名是用戶數(shù)據(jù)報協(xié)議,?是?OSI?(Open?System?Interconnection,?開放式系統(tǒng)互聯(lián))參考模型中一種無連接的傳輸層協(xié)議,在網(wǎng)絡(luò)中它與?TCP?協(xié)議一樣用于處理數(shù)據(jù)包,是一種無連接的協(xié)議。

????????在?OSI?模型中,UDP和TCP一樣,在傳輸層(第四層),處于?IP?協(xié)議的上一層。UDP?協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)包的形式。一個典型的數(shù)據(jù)包就是一個二進制數(shù)據(jù)的傳輸單位。每一個數(shù)據(jù)包的前?8?個字節(jié)用來包含報頭信息,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)。UDP?有不提供數(shù)據(jù)包分組、組裝和不能對數(shù)據(jù)包進行排序的缺點,也就是說,當(dāng)報文發(fā)送之后,是無法得知其是否安全完整到達的。

????????簡單來說UDP就是沒有確TCP協(xié)議。TCP每發(fā)出一個數(shù)據(jù)包都要求確認,如果有一個數(shù)據(jù)包丟失,就收不到確認,發(fā)送方就必須重發(fā)這個數(shù)據(jù)包。為了保證傳輸?shù)目煽啃?,TCP協(xié)議在UDP基礎(chǔ)之上建立了三次對話的確認機制,即在正式收發(fā)數(shù)據(jù)前,必須和對方建立可靠的連接。TCP數(shù)據(jù)包和UDP一樣,都是由首部和數(shù)據(jù)兩部分組成,唯一不同的是,TCP數(shù)據(jù)包沒有長度限制,理論上可以無限長,但是為了保證網(wǎng)絡(luò)的效率,通常TCP數(shù)據(jù)包的長度不會超過IP數(shù)據(jù)包的長度,以確保單個TCP數(shù)據(jù)包不必再分割。

????????UDP?用來支持那些需要在計算機之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用。?包括網(wǎng)絡(luò)視頻會議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用?UDP?協(xié)議。?UDP?協(xié)議從問世至今已經(jīng)被使用了很多年,?雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋,但是即使是在今天?UDP?仍然不失為一項非常實用和可行的網(wǎng)絡(luò)傳輸層協(xié)議。

? ? ? ? 下圖是UDP的傳輸過程,可以看到相比于TCP協(xié)議,UDP簡化了一些步驟:

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)
UDP傳輸過程

????????這一部分原理和TCP部分大致相同,因為網(wǎng)上找到的例程有點小bug還沒有解決,所以暫時先簡單分享一下UDP方面的思路,后續(xù)理解了會更新完整代碼,關(guān)鍵實現(xiàn)代碼如下(led燈在另一個文件中已經(jīng)定義,此處也可以刪掉):

esp32 ipv6,基于ESP32的物聯(lián)網(wǎng)開發(fā)設(shè)計,物聯(lián)網(wǎng),嵌入式硬件,vscode,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)

參考代碼如下:

static struct sockaddr_in dest_addr;                  //遠端地址
socklen_t dest_addr_socklen = sizeof(dest_addr);
static int udp_socket = 0;                          //連接socket
TaskHandle_t xUDPRecvTask = NULL;

void udp_send_data(char* data, int len)
{

    if(udp_socket>0){

        int err = sendto(udp_socket, data, len, 0, (struct sockaddr *)&dest_addr, dest_addr_socklen);
        if (err < 0)   printf( "Error occurred during sending: errno %d", errno);
    }
}

void udp_recv_data(void *pvParameters){
    socklen_t socklen = sizeof(dest_addr);
    uint8_t rx_buffer[1024] = {0};
    printf("create udp recv\n");

    while (1)
    {
        int len = recvfrom(udp_socket, rx_buffer, sizeof(rx_buffer) - 1, 0,  (struct sockaddr *)&dest_addr, &dest_addr_socklen);
        if(len > 0){
            if(len == 2 && rx_buffer[0]=='o' && rx_buffer[1]=='n')  led_red(LED_ON);
            else if(len == 3 && rx_buffer[0]=='o' && rx_buffer[1]=='f' && rx_buffer[2]=='f')     led_red(LED_OFF);
            else
            {
                rx_buffer[len] = 0; //未尾增加"\0,確保長度"
                printf("Received %d bytes: %s.\n", len, rx_buffer);
                udp_send_data((char*)rx_buffer, len);
            }
        }
    }
}

void udp_ini_client(void *pvParameters){
    if(udp_socket>0){
        close(udp_socket);
        udp_socket=0;
    }
    udp_socket = socket(AF_INET,SOCK_DGRAM,0);
    printf("connect_socket:%d\n",udp_socket);

    if(udp_socket < 0){
       printf( "Unable to create socket: errno %d", errno);
       return;
    }

    dest_addr.sin_addr.s_addr = inet_addr("255.255.255.255"); 
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(UDP_PORT);//目標(biāo)端口
    printf("Socket created, sending to 255.255.255.255:%d", UDP_PORT);

    struct sockaddr_in Loacl_addr;
    Loacl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    Loacl_addr.sin_family = AF_INET;
    Loacl_addr.sin_port = htons(UDP_PORT); 

    uint8_t res = 0;
    res = bind(udp_socket,(struct sockaddr *)&Loacl_addr,sizeof(Loacl_addr));
    if(res != 0){
        printf("bind error\n");
    }

    if(xUDPRecvTask != NULL){
        vTaskDelete(xUDPRecvTask);
        xUDPRecvTask = NULL;
    }

    xTaskCreate(&udp_recv_data,"udp_recv_data",2048*2,NULL,10,&xUDPRecvTask);
    vTaskDelete(NULL);
}

void create_udp()
{
    xTaskCreate(&udp_ini_client, "udp_ini_client", 4096, NULL, 5, NULL);
}

總結(jié)

? ? ? ? 對于第一次接觸本地控制來說,tcp/ip真的可以算是一個難啃的骨頭,會有很多新的概念,會綜合很多部分的使用;最重要的是,不同例程的思路也迥然不同,官方的例程不夠全面也沒有注解,而第三方的例程有時候的定義和用法又需要重新理解,還有一些嵌套的思路有時候就像解一團繩結(jié)一樣,如果不是對整體特別熟練,理解起來也會非常頭大。

????????從全局的角度一點點入手,分解、拆開之后,會清晰很多;有些小塊不懂的地方其實也不用死磕,可以先記錄下來,之后再一點點看,慢慢會有一些思路,很多問題在不知不覺中就明白了。

? ? ? ? 這章主要還是聊的局域網(wǎng)內(nèi)的本地控制,現(xiàn)在我們在同一個wifi下已經(jīng)能通過電腦遠程控制板子了,再加上之前的smart config,可以做出一些不錯的嘗試。下一章更近一步,通過MQTT協(xié)議和HTTP協(xié)議的學(xué)習(xí),獲得聯(lián)網(wǎng)信息,再到接入esp rainmaker,達到遠程控制。
????????文章來源地址http://www.zghlxwxcb.cn/news/detail-603263.html

到了這里,關(guān)于4·ESP32-C3入門教程——從本地控制走向云端控制(TCP/IP UDP篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【ESP32入門教程】ESP32開發(fā)板原理圖,引腳圖,引腳功能,ESP WROOM 32,介紹ESP32硬件

    【ESP32入門教程】ESP32開發(fā)板原理圖,引腳圖,引腳功能,ESP WROOM 32,介紹ESP32硬件

    記錄本人學(xué)習(xí)歷程,同時也分享給大家學(xué)習(xí),僅供參考! 模組共有38個管腳,具體描述如下。 1. GPIO6至GPIO11 引腳 控制集成在模組內(nèi)部的SPI Flash, 不建議用于其他功能 。 SCK/CLK GPIO6 SDO/SD0 GPIO7 SDI/SD1 GPIO8 SHD/SD2 GPIO9 SWP/SD3 GPIO10 SCS/CMD GPIO11 2.Strapping 管腳 ESP32共有5個Strapping管腳,。

    2024年02月08日
    瀏覽(40)
  • Arduino ESP32開發(fā)環(huán)境搭建入門教程,esp32的arduino開發(fā)環(huán)境搭建教程,arduino導(dǎo)入eps32開發(fā)插件

    Arduino ESP32開發(fā)環(huán)境搭建入門教程,esp32的arduino開發(fā)環(huán)境搭建教程,arduino導(dǎo)入eps32開發(fā)插件

    從官網(wǎng)下載 Arduino IDE 軟件并安裝。下載鏈接:Software | Arduino 網(wǎng)盤鏈接:鏈接:https://pan.baidu.com/s/1ZuSbo1BPy8XyyXzfl4KNzg?pwd=f8yd 提取碼:f8yd 1、找到Arduino IDE安裝目錄,打開hardware文件夾。 2、在hardware文件夾中創(chuàng)建一個espressif文件夾。 3、將解壓出的文件夾移動到espressif文件夾中,

    2024年02月13日
    瀏覽(32)
  • ESP系列入門教程(一)——之用繼電器簡單驅(qū)動一個LED【附 ESP32 / ESP8266 通用代碼】

    ESP系列入門教程(一)——之用繼電器簡單驅(qū)動一個LED【附 ESP32 / ESP8266 通用代碼】

    最近在跟著幾個大佬的教學(xué)視頻做項目。陸續(xù)會更新記錄一些要點,便于后期總結(jié)筆記的時候進行引用。 也可以幫助有心跟著一起復(fù)刻的寶子們,更好地捋清思路。 【本系列教程 - 總目標(biāo)】: 使用ESP系列板卡,通過MQTT進行數(shù)據(jù)通信,達到遠程控制多個傳感器的效果。 ◆配

    2024年01月19日
    瀏覽(29)
  • c3p0 數(shù)據(jù)池入門使用教程

    從零開始手寫 mybatis (三)jdbc pool 如何從零手寫實現(xiàn)數(shù)據(jù)庫連接池 dbcp? 萬字長文深入淺出數(shù)據(jù)庫連接池 HikariCP/Commons DBCP/Tomcat/c3p0/druid 對比 Database Connection Pool 數(shù)據(jù)庫連接池概覽 c3p0 數(shù)據(jù)池入門使用教程 alibaba druid 入門介紹 數(shù)據(jù)庫連接池 HikariCP 性能為什么這么快? Apache

    2024年03月15日
    瀏覽(16)
  • [入門教程]詳細講解STM32控制LED點陣屏(HUB75接口)

    [入門教程]詳細講解STM32控制LED點陣屏(HUB75接口)

    本文適合初級入門的同學(xué),大佬請繞道。講解怎么用stm32驅(qū)動成品LED點陣屏顯示一副七色無灰度的圖片,有灰度的圖片可以入門后繼續(xù)研究。 ? 使用軟硬件: 軟件:Keil5,程序在后面會給出 硬件:STM32F103最小系統(tǒng)、全彩色P4LED點陣屏(HUB75接口,16掃) 說下stm32驅(qū)動LED點陣屏用

    2024年01月19日
    瀏覽(97)
  • 【esp32c3配置arduino IDE教程】

    【esp32c3配置arduino IDE教程】

    本文主線FastBond2階段1——基于ESP32C3開發(fā)的簡易IO調(diào)試設(shè)備,esp32c3環(huán)境搭建,設(shè)計目標(biāo)如下 設(shè)計用戶操作界面,該設(shè)備具備簡單易用的操作界面,外加顯示屏SSD1306和旋轉(zhuǎn)編碼器進行顯示和控制,用戶后期可進行二次開發(fā)WiFi或藍牙連接電腦或手機監(jiān)控。 多種數(shù)字和模擬信號的

    2024年02月03日
    瀏覽(22)
  • 006.合宙ESP32-C3+藍牙調(diào)試器通過BLE發(fā)送接收數(shù)據(jù)教程

    006.合宙ESP32-C3+藍牙調(diào)試器通過BLE發(fā)送接收數(shù)據(jù)教程

    在平衡小車制作過程中,需要對KP/KD/KSP/KSI等PID系數(shù)進行調(diào)試,而平衡小車無法通過USB等進行有線調(diào)試,而ESP32-C3自帶藍牙+WIFI,使用WIFI比較吃算力,故選擇通過藍牙進行調(diào)參,同時能夠?qū)ngle/Encoder/PWM等數(shù)據(jù)回傳至手機端進行查看。 前期通過查找資料,發(fā)現(xiàn)合宙ESP32-C3自帶藍

    2024年02月03日
    瀏覽(24)
  • 新上架的簡約版合宙ESP32C3使用arduino開發(fā)的教程

    新上架的簡約版合宙ESP32C3使用arduino開發(fā)的教程

    經(jīng)過兩個月的缺貨下架后,9塊9包郵的合宙ESP32C3又重新上架了,真香。這一批都是沒有帶串口芯片的簡約版(9塊9要啥自行車)。在下架前,簡約版要使用2.0.0版本的ESP32開發(fā)板庫才能下載,而2.0.0版本有一些丟失arduino自帶庫的詭異BUG,所以一直沒法用于下載?,F(xiàn)在由于發(fā)布了2

    2024年02月05日
    瀏覽(28)
  • ESP32-C3 應(yīng)用 篇(實例二、通過藍牙將傳感器數(shù)據(jù)發(fā)送給手機,手機端控制 SK6812 LED)

    ESP32-C3 應(yīng)用 篇(實例二、通過藍牙將傳感器數(shù)據(jù)發(fā)送給手機,手機端控制 SK6812 LED)

    前面文章說過,藍牙協(xié)議博主了解不是很深入,只進行一些基礎(chǔ)的了解,示例的測試,和初學(xué)者一樣,基本上藍牙專欄系列博文都是一步一步摸索過來的,功夫不負有心人,到目前為止,多多少少對藍牙 GATT 有了一定的認識。 那么我們今天就要學(xué)以致用,使用 ESP32-C3 的藍牙

    2024年02月09日
    瀏覽(17)
  • 物聯(lián)網(wǎng)開發(fā)筆記(89)- 使用Micropython開發(fā)ESP32開發(fā)板之合宙ESP32 C3開發(fā)板通過串口SPI控制st7789 TFT液晶屏1.3寸

    物聯(lián)網(wǎng)開發(fā)筆記(89)- 使用Micropython開發(fā)ESP32開發(fā)板之合宙ESP32 C3開發(fā)板通過串口SPI控制st7789 TFT液晶屏1.3寸

    一、目的 ??????? 這一節(jié)我們學(xué)習(xí)如何使用合宙的ESP32 C3開發(fā)板控制1.3寸彩色TFT顯示屏模塊,分辨率240*240,SPI接口,ST7789驅(qū)動芯片。 二、環(huán)境 ??????? ESP32? C3 + Thonny + 1.3寸 st7789液晶屏模塊 + 幾根杜邦線 + Win10 接線方法: ? 三、st7789 TFT顯示屏驅(qū)動 st7789py.py ? 四、點亮

    2024年02月11日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包