使用Wi-Fi实现ESP32与手机网络助手进行TCP数据收发

在ESP32板块,开发环境搭建完成的基础上,做一个简单的TCP客户端与服务器端的数据收发实验,开发环境是基于乐鑫官方IDF,Linux环境下发开,本实验有助于对例程的理解和应用。

实验前期准备:在手机上下载一个“网络调试助手”APP,并做如下设置。

1.Server地址为自动分配

2.设置手机为Server

3.设置端口号8080,可设置其他

实验总体概述:

Step1:ESP32 Wi-Fi设置为STA模式,将其连接到路由器(AP)上

Step2:使用IPv4,TCP协议,ESP32作为Client

Step3:将手机连接到同一个路由器上,使手机IP与ESP32 STA IP处于同一个网段下,我的即是192.168.1,并设置为Server(准备阶段已完成)

Step4:实现Client和Server间数据的收发

实验具体实现:

参考官方IDF,例程目录esp\esp-idf\examples\protocols\sockets\tcp_client

Client端实现的关键代码分析,初始化Wi-Fi配置,设置为sta模式,ssid为连接AP名,password为密码

#define EXAMPLE_WIFI_SSID   "2-401-meeting"
#define EXAMPLE_WIFI_PASS   "1122334455"

/*sta结构体关键成员初始化*/
wifi_config_t wifi_config = 
{
    .sta = 
    {
        .ssid = EXAMPLE_WIFI_SSID,
        .password = EXAMPLE_WIFI_PASS,
    },
};

配置TCP网络协议栈,设置Server地址(我的即为192.168.1.112),端口号8080

#define HOST_IP_ADDR "192.168.1.112"    //Server IP address
#define PORT    8080
#define IPPROTO_IP    0

struct sockaddr_in destAddr;
destAddr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;

Client客户端socket实现代码,首先创建socket描述符,然后连接server


while(1)
{
    /* 创建socket */
    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");
    
    /* 连接server */
    int err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
    if (err != 0) 
    {
        ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
        break;
    }
    ESP_LOGI(TAG, "Successfully connected");
}

Client收发数据,完整代码可查看IDF相关例程

while (1) 
{
    /* 发送数据 */
    int err = send(sock, payload, strlen(payload), 0);
    if (err < 0) 
    {
        ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
        break;
    }
    /* 接收数据 */
    int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
    // Error occured 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, addr_str);
        ESP_LOGI(TAG, "%s", rx_buffer);
    }

    vTaskDelay(2000 / portTICK_PERIOD_MS);
}

在Linux终端中使用命令make monitor(在工程所在目录下的脚本命令),观察Client收发数据结果

手机Server收发数据结果

  • 5
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是基于 ESP32-C3 和 esp-idf 4.3.5 的 TCP 客户端非阻塞式循环收发的示例代码: ```c #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" #include "esp_system.h" #include "nvs_flash.h" #include "esp_netif.h" #include "esp_tls.h" #include "lwip/err.h" #include "lwip/sys.h" #include "lwip/sockets.h" #define WIFI_SSID "your_wifi_ssid" #define WIFI_PASS "your_wifi_password" #define SERVER_IP "server_ip_address" #define SERVER_PORT 12345 static const char *TAG = "tcp_client"; static void wifi_init_sta(void) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_wifi_set_mode(WIFI_MODE_STA); wifi_config_t wifi_config = { .sta = { .ssid = WIFI_SSID, .password = WIFI_PASS, }, }; esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config); esp_wifi_start(); } void tcp_client_task(void *pvParameters) { char rx_buffer[128]; char addr_str[128]; int addr_family; int ip_protocol; struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = inet_addr(SERVER_IP); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(SERVER_PORT); addr_family = AF_INET; ip_protocol = IPPROTO_IP; inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1); int sock = socket(addr_family, SOCK_STREAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); vTaskDelete(NULL); return; } ESP_LOGI(TAG, "Socket created, connecting to %s:%d", SERVER_IP, SERVER_PORT); if (connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) != 0) { ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno); close(sock); vTaskDelete(NULL); return; } ESP_LOGI(TAG, "Successfully connected"); while (1) { int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); if (len < 0) { ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno); break; } else if (len == 0) { ESP_LOGW(TAG, "Connection closed"); break; } else { rx_buffer[len] = '\0'; ESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer); } int err = send(sock, "Hello Server!", strlen("Hello Server!"), 0); if (err < 0) { ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno); break; } ESP_LOGI(TAG, "Message sent"); vTaskDelay(1000 / portTICK_PERIOD_MS); } if (sock != -1) { ESP_LOGE(TAG, "Shutting down socket and restarting..."); shutdown(sock, SHUT_RDWR); close(sock); } vTaskDelete(NULL); } void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); esp_netif_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); wifi_init_sta(); xTaskCreate(tcp_client_task, "tcp_client_task", 4096, NULL, 5, NULL); } ``` 在这个示例代码中,我们创建了一个 TCP 客户端,连接到指定的服务器 IP 地址和端口。在循环中,我们通过 `recv` 函数接收服务器发送的数据,并通过 `send` 函数发送数据到服务器。需要注意的是,这两个函数都是非阻塞式的,因此任务可以在等待数据时执行其他操作。 在 `app_main` 函数中,我们初始化了 Wi-Fi 并创建了我们的 TCP 客户端任务。 请记得将示例代码中的 `WIFI_SSID`、`WIFI_PASS`、`SERVER_IP` 和 `SERVER_PORT` 替换为你的实际值。 希望这个示例代码对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值