You need to enable JavaScript to run this app. ESP32与Python TCP服务器双向通信:服务端下发JSON问题求助
优惠活动
大模型
产品
解决方案
定价
更多

ESP32与Python TCP服务器双向通信:服务端下发JSON问题求助

ESP32与Python TCP服务端双向通信可落地修正方案

现存核心问题定位

  • Python服务端时序逻辑错误:原代码将发送数据的代码放在recv循环退出之后,只有当ESP32完全断开连接时才会触发发送动作,此时ESP32已经处于断连流程中,根本无法接收数据;同时原代码构造的JSON字符串存在语法错误,{"accel","gyro","time":1}缺失键值对冒号,不属于合法JSON格式;s.listen(0)将全连接队列长度设为0,易导致连接被内核直接丢弃。
  • ESP32端接收逻辑错误:发送完上报数据后立刻读取服务端返回,未考虑TCP传输的网络延迟,此时服务端返回的报文还未到达ESP32缓存区,直接读取会拿到空值;代码中重复定义char c变量,存在编译错误;仅读1个字符就停止接收,无法读完整段JSON报文,读完后立刻执行断连操作,没有给传输留足缓冲时间。

修正后的Python TCP服务端代码

import socket

s = socket.socket()
# 监听地址保持不变,将全连接队列长度设为1,满足单设备通信需求
s.bind(('192.168.1.11', 5000))
s.listen(1)

while True:
    client, addr = s.accept()
    print(f"收到来自{addr}的新连接")
    # 构造合法的JSON指令字符串
    send_cmd = bytes('{"accel":0.1,"gyro":0.2,"time":123456}', "utf-8")

    while True:
        content = client.recv(32)
        if len(content) == 0:
            # 仅当ESP32主动触发断连时才退出接收循环
            break
        else:
            print(f"收到ESP32上报数据: {content}")

    # 调整发送时机:收到ESP32上报数据后立刻发送指令,不等断连
    client.send(send_cmd)
    # 给连接设置2秒超时,等待ESP32处理完接收后再关闭连接
    client.settimeout(2)
    try:
        while client.recv(1024):
            pass
    except socket.timeout:
        pass

    print("Closing connection")
    client.close()

修正后的ESP32(Arduino框架)代码

#include <WiFi.h>
#include <WiFiClient.h>

const char* ssid = "#########";
const char* password =  "######";
 
const uint16_t port = 5000;
const char * host = "192.168.1.11";
// 定义全局WiFiClient实例,无需每次循环新建对象
WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(2000);
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("WiFi连接中...");
  }
 
  Serial.print("WiFi已连接,设备IP: ");
  Serial.println(WiFi.localIP());
}
 
void loop() {
  // 检测连接状态,自动重连
  if (!client.connected()) {
    Serial.println("连接已断开,尝试重新连接服务端...");
    if (!client.connect(host, port)) {
      Serial.println("连接服务端失败,1秒后重试");
      delay(1000);
      return;
    }
    Serial.println("已成功连接到服务端!");
  }
 
  // 发送ESP32端的上报数据
  client.print("Hello from ESP32!");
 
  // 留100ms网络传输延迟,避免立刻读缓存拿空值
  delay(100);
  String recv_buffer = "";
  // 设置5秒接收超时,避免无限等待
  uint32_t recv_start_time = millis();
  while (millis() - recv_start_time < 5000) {
    if (client.available()) {
      char c = client.read();
      recv_buffer += c;
      // 读到JSON结束的右大括号时判定一帧接收完成
      if (c == '}') {
        break;
      }
    }
  }

  if (recv_buffer.length() > 0) {
    Serial.print("收到服务端JSON指令: ");
    Serial.println(recv_buffer);
  }

  // 留2秒缓冲时间,等数据完全传输完成再断连
  delay(2000);
  Serial.println("断开当前连接...");
  client.stop();
 
  delay(10000);
}

落地验证注意事项

  • 确保ESP32和运行Python服务端的设备处于同一个局域网,且Python端防火墙已放行5000端口的入站规则,否则会出现ESP32能发数据但收不到返回的情况
  • 发送的JSON字符串必须保证语法合法,缺失冒号、多写逗号的格式错误会直接导致ESP32端解析失败
  • TCP属于流式传输协议,本身没有固定报文边界,必须通过自定义结束标识(比如JSON的右大括号)判断一帧接收完成,不能指望单次读取就能拿到完整报文

内容的提问来源于stack exchange,提问作者Senuda Jayalath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.11 07:36:04