一、TCP与UDP协议对比
1.1 基本特性比较
TCP(传输控制协议)和UDP(用户数据报协议)是两种最常用的传输层协议,它们在ESP32网络编程中都有广泛应用:
-
「连接方式」
-
TCP是面向连接的协议,通信前需要先建立连接(三次握手) -
UDP是无连接的协议,直接发送数据包 -
「可靠性」
-
TCP提供可靠传输,保证数据无差错、不丢失、不重复且按序到达 -
UDP提供尽力而为的交付,不保证可靠性 -
「实时性」
-
UDP具有更好的实时性,传输效率更高 -
TCP由于重传机制和流量控制,实时性相对较低 -
「连接模式」
-
TCP仅支持点到点通信 -
UDP支持一对一、一对多、多对多等多种通信模式 -
「资源消耗」
-
TCP需要维护连接状态,系统资源消耗较大 -
UDP实现简单,资源消耗较少
1.2 ESP32中的协议栈支持
ESP-IDF使用开源的lwIP轻量级TCP/IP协议栈,并对原始版本进行了优化和扩展:
-
支持BSD Socket API标准接口 -
支持Netconn API(但官方不推荐使用) -
针对嵌入式系统进行了内存优化 -
支持IPv4和IPv6双协议栈
二、TCP服务器核心API
2.1 关键Socket函数
ESP32通过BSD Socket接口实现TCP通信,主要API包括:
-
「socket()」 – 创建通信端点 -
「bind()」 – 绑定本地地址和端口 -
「listen()」 – 开始监听连接请求 -
「accept()」 – 接受客户端连接 -
「recv()/send()」 – 接收/发送数据 -
「shutdown()/close()」 – 关闭连接
2.2 特殊功能支持
除了标准BSD Socket API外,ESP32还支持:
-
「fcntl()」 – 控制socket属性 -
「ioctl()」 – I/O设备控制 -
「select()」 – I/O多路复用 -
「poll()」 – (通过select实现)
三、TCP服务器实现流程
3.1 完整实现步骤
-
「创建socket」
int listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if(listen_sock < 0) {
ESP_LOGE(TAG, "创建socket失败: errno %d", errno);
} -
「配置服务器地址」
struct sockaddr_in dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_port = htons(TCP_PORT); -
「绑定地址」
int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if(err != 0) {
ESP_LOGE(TAG, "绑定失败: errno %d", errno);
close(listen_sock);
} -
「开始监听」
err = listen(listen_sock, 1); // 参数1表示最大等待连接数
if(err != 0) {
ESP_LOGE(TAG, "监听失败: errno %d", errno);
close(listen_sock);
} -
「接受连接」
struct sockaddr_in6 source_addr;
uint addr_len = sizeof(source_addr);
int connect_sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len); -
「数据收发」
// 接收数据
len = recv(connect_sock, rx_buffer, sizeof(rx_buffer), 0);
// 发送数据
send(connect_sock, tx_buffer, len, 0);
3.2 连接管理注意事项
-
每个accept()会创建一个新的socket专门用于该连接 -
原始监听socket继续用于接受新连接 -
需要合理管理连接资源,及时关闭不再使用的socket -
对于多客户端场景,建议使用多任务或select/poll管理
四、Wi-Fi模式配置
4.1 Station模式(连接路由器)
// 使用示例提供的辅助函数连接Wi-Fi
ESP_ERROR_CHECK(example_connect());
4.2 AP模式(创建热点)
void wifi_init_softap(void) {
// 初始化网络接口
esp_netif_create_default_wifi_ap();
// 配置AP参数
wifi_config_t wifi_config = {
.ap = {
.ssid = "ESP32_AP",
.password = "12345678",
.max_connection = 4,
.authmode = WIFI_AUTH_WPA_WPA2_PSK
},
};
// 启动AP
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
五、完整示例代码分析
5.1 主任务流程
void app_main(void)
{
// 初始化NVS存储
ESP_ERROR_CHECK(nvs_flash_init());
// 初始化网络
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 连接Wi-Fi(Station模式)或创建AP
// ESP_ERROR_CHECK(example_connect()); // Station模式
wifi_init_softap(); // AP模式
// 创建TCP服务器任务
xTaskCreate(tcp_server_task, "tcp_server", 4096, (void*)AF_INET, 5, NULL);
}
5.2 TCP服务器任务
static void tcp_server_task(void *pvParameters)
{
// 1. 创建socket
int listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
// 2. 绑定地址
struct sockaddr_in dest_addr;
// ... 配置地址 ...
bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
// 3. 开始监听
listen(listen_sock, 1);
while(1) {
// 4. 接受新连接
int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
// 5. 处理连接
do_retransmit(sock);
// 6. 关闭连接
close(sock);
}
}
5.3 数据传输处理
static void do_retransmit(const int sock)
{
char rx_buffer[128];
while(1) {
// 接收数据
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
if(len > 0) {
// 处理接收到的数据
process_data(rx_buffer, len);
// 发送响应
send(sock, response, response_len, 0);
} elseif(len == 0) {
// 连接关闭
break;
} else {
// 错误处理
handle_error();
}
}
}
六、性能优化与调试
6.1 常见问题解决
-
「连接失败」
-
检查Wi-Fi连接状态 -
确认端口未被占用 -
检查防火墙设置 -
「数据传输不稳定」
-
增加接收缓冲区大小 -
实现重传机制 -
优化任务优先级 -
「内存不足」
-
调整lwIP内存池大小 -
及时释放socket资源 -
使用内存优化配置
6.2 配置选项
通过menuconfig配置关键参数:
idf.py menuconfig
重要配置项:
-
Component config → LWIP → 内存配置 -
Example Connection Configuration → Wi-Fi/以太网设置 -
Example Configuration → 服务器端口号
七、应用场景扩展
7.1 物联网控制
-
实现远程设备控制 -
状态监控与数据采集 -
固件OTA升级
7.2 工业应用
-
设备间可靠通信 -
实时数据传输 -
远程诊断与维护
7.3 智能家居
-
家庭设备组网 -
集中控制与管理 -
安全通信保障
通过合理设计和优化,ESP32 TCP服务器可以满足各种物联网应用的通信需求,提供稳定可靠的数据传输服务。