ESP32-C3, esp-idf 4.3.5,tcp client 非阻塞式循环收发,带断开重连机制,提供一个例程
时间: 2024-01-01 19:05:42 浏览: 226
tcp client简单实例 连接,发送接收断开,多线程
5星 · 资源好评率100%
好的,以下是一个 ESP32-C3 上使用 esp-idf 4.3.5 开发的 TCP client 非阻塞式循环收发的例程,同时带有断开重连机制:
```c
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <esp_log.h>
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_err.h>
#include <esp_system.h>
#include <esp_timer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
/* WiFi 相关配置 */
#define WIFI_SSID "your_wifi_ssid"
#define WIFI_PASSWORD "your_wifi_password"
/* TCP Client 相关配置 */
#define SERVER_ADDRESS "your_server_address" // 服务器地址
#define SERVER_PORT 12345 // 服务器端口号
#define RECONNECT_DELAY 5000 // 重连延时,单位:毫秒
#define BUFFER_SIZE 1024 // 接收缓冲区大小
static const char *TAG = "tcp_client";
static EventGroupHandle_t s_wifi_event_group;
static const int WIFI_CONNECTED_BIT = BIT0;
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
ESP_LOGI(TAG, "Wi-Fi disconnected");
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ESP_LOGI(TAG, "Wi-Fi connected, IP address: %s", ip4addr_ntoa((const ip4_addr_t *)&event_data));
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
static void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASSWORD,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "Wi-Fi connected");
} else {
ESP_LOGE(TAG, "Wi-Fi connection failed");
}
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
vEventGroupDelete(s_wifi_event_group);
}
static void tcp_client_task(void *arg)
{
int sockfd;
struct sockaddr_in server_addr = {
.sin_family = AF_INET,
.sin_port = htons(SERVER_PORT),
};
struct hostent *server = gethostbyname(SERVER_ADDRESS);
bcopy(server->h_addr, &server_addr.sin_addr.s_addr, server->h_length);
char rx_buffer[BUFFER_SIZE] = {0};
int rx_len = 0;
while (1) {
// 创建 socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
ESP_LOGE(TAG, "Failed to create socket (%d)", errno);
vTaskDelay(RECONNECT_DELAY / portTICK_PERIOD_MS);
continue;
}
// 连接服务器
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
ESP_LOGE(TAG, "Failed to connect to server (%d)", errno);
close(sockfd);
vTaskDelay(RECONNECT_DELAY / portTICK_PERIOD_MS);
continue;
}
ESP_LOGI(TAG, "Connected to server");
while (1) {
// 检查 Wi-Fi 连接状态
EventBits_t bits = xEventGroupGetBits(s_wifi_event_group);
if (!(bits & WIFI_CONNECTED_BIT)) {
ESP_LOGE(TAG, "Wi-Fi disconnected");
break;
}
// 接收数据
rx_len = recv(sockfd, rx_buffer, BUFFER_SIZE, 0);
if (rx_len > 0) {
rx_buffer[rx_len] = '\0';
ESP_LOGI(TAG, "Received: %s", rx_buffer);
} else if (rx_len < 0) {
ESP_LOGE(TAG, "Failed to receive data (%d)", errno);
break;
} else {
ESP_LOGI(TAG, "Server closed the connection");
break;
}
// 发送数据
const char *tx_buffer = "Hello, server!";
if (send(sockfd, tx_buffer, strlen(tx_buffer), 0) < 0) {
ESP_LOGE(TAG, "Failed to send data (%d)", errno);
break;
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// 关闭 socket
close(sockfd);
ESP_LOGI(TAG, "Disconnected from server");
}
}
void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
tcpip_adapter_init();
wifi_init_sta();
xTaskCreate(tcp_client_task, "tcp_client_task", 8192, NULL, 5, NULL);
}
```
在该例程中,我们使用了 FreeRTOS 中的任务来实现 TCP client 的非阻塞式循环收发,并且在 Wi-Fi 断开连接时会自动重连。在 main 函数中,我们首先对 NVS 进行初始化,然后初始化 Wi-Fi STA 模式,最后创建一个 TCP client 任务。
该例程中使用了 Event Group 来检查 Wi-Fi 连接状态,当 Wi-Fi 连接成功后,我们就可以创建一个 socket,并连接到服务器。在连接成功后,我们会进入一个循环中,不断地接收来自服务器的数据,并发送数据给服务器。当 Wi-Fi 断开连接时,我们会关闭当前的 socket,然后等待重连。
以上就是一个 ESP32-C3 上使用 esp-idf 4.3.5 开发的 TCP client 非阻塞式循环收发的例程,带有断开重连机制。
阅读全文