ESP32-C3, esp-idf 4.3.5,tcp client 非阻塞式循环收发,带断开重连机制,提供一个例程
时间: 2024-01-01 14:05:42 浏览: 179
好的,以下是一个 ESP32-C3 的 TCP Client 非阻塞式循环收发并带有断开重连机制的示例代码。在这个例程中,我们使用了 FreeRTOS 中的定时器来定时检查连接状态并进行重连。
```c
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "lwip/sockets.h"
#define WIFI_SSID "your_wifi_ssid"
#define WIFI_PASS "your_wifi_password"
#define SERVER_IP "your_server_ip"
#define SERVER_PORT 1234
static const char *TAG = "tcp_client";
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
static bool tcp_connected = false;
static int tcp_socket = -1;
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
switch (event_id) {
case WIFI_EVENT_STA_START:
esp_wifi_connect();
break;
case WIFI_EVENT_STA_CONNECTED:
ESP_LOGI(TAG, "Wi-Fi connected");
break;
case WIFI_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "Wi-Fi disconnected");
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
}
static void tcp_client_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family;
int ip_protocol;
while (1) {
if (!tcp_connected) {
// Connect to server
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;
tcp_socket = socket(addr_family, SOCK_STREAM, ip_protocol);
if (tcp_socket < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created");
int err = connect(tcp_socket, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
close(tcp_socket);
tcp_socket = -1;
vTaskDelay(1000 / portTICK_PERIOD_MS);
continue;
}
tcp_connected = true;
ESP_LOGI(TAG, "Successfully connected");
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
}
// Receive data
int len = recv(tcp_socket, rx_buffer, sizeof(rx_buffer) - 1, 0);
if (len < 0) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
tcp_connected = false;
close(tcp_socket);
tcp_socket = -1;
continue;
} else if (len == 0) {
ESP_LOGI(TAG, "Connection closed");
tcp_connected = false;
close(tcp_socket);
tcp_socket = -1;
continue;
}
rx_buffer[len] = 0;
ESP_LOGI(TAG, "Received %d bytes: %s", len, rx_buffer);
// Send data
const char *tx_buffer = "Hello from ESP32";
int err = send(tcp_socket, tx_buffer, strlen(tx_buffer), 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
tcp_connected = false;
close(tcp_socket);
tcp_socket = -1;
continue;
}
ESP_LOGI(TAG, "Message sent");
}
vTaskDelete(NULL);
}
static void wifi_init_sta()
{
wifi_event_group = xEventGroupCreate();
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
},
};
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "Wi-Fi init finished");
// Wait for connection
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
// Start TCP client task
xTaskCreate(tcp_client_task, "tcp_client_task", 4096, NULL, 5, NULL);
}
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_LOGI(TAG, "ESP32-C3 TCP client example");
// Initialize Wi-Fi
wifi_init_sta();
}
```
在这个例程中,我们使用了 FreeRTOS 的定时器来检测连接状态并进行重连。这个定时器每秒钟会执行一次,判断连接状态是否正常,如果连接断开了,就会重新连接。请注意,这个定时器只是一个示例,您可以根据自己的需求进行调整。
希望这个例程能够帮助到您。如果您有任何问题或疑问,请随时联系我。
阅读全文