ESP-01客户端无法接收WiFi服务器返回数据的技术求助
ESP8266 WiFi客户端无法接收服务器回复的问题解决
问题概述
使用ESP8266WiFi库(3.0.2版本)实现两台ESP-01的WiFi通信:客户端向端口5000的服务器发送2字节数据,可正常触发服务器端继电器引脚翻转,但客户端始终无法接收服务器的操作确认回复。库提示server.write()未实现,需使用server.accept()替代server.available(),但未找到可用示例,尝试参考client.print()相关内容也未解决问题。客户端发送数据后会循环10秒尝试接收,无返回后会再次请求翻转继电器,此循环可稳定运行数小时。
核心错误与排查建议
- 服务器端回复对象错误:
服务器端当前使用server.println()发送回复,这是错误的——WiFiServer对象仅负责监听新连接,实际与客户端的通信必须通过已建立连接的WiFiClient实例完成。这是客户端收不到回复的直接原因。 - 关于
server.accept()与server.available():
在ESP8266WiFi库3.x版本中,server.available()仍然可以正常使用,server.accept()是其替代方法,两者均用于获取连接的客户端对象,区别在于accept()仅返回新建立的连接,而available()可能返回已存在的连接。
修正后的代码
通用定义(无需修改)
#include <ESP8266WiFi.h> const char* ssid = "blablabla"; const char* password = "blublublu"; #define SERVER_PORT 5000 #define RELAY 0 // 通信协议定义 enum Protocol{ PIN, // 要控制的引脚编号 VALUE, // 引脚目标电平(HIGH=1 / LOW=0) BUFFER_SIZE // 协议缓冲区大小,必须作为枚举最后一项 };
修正后的服务器端代码
WiFiServer server(SERVER_PORT); void setup() { Serial.begin(115200); pinMode(RELAY, OUTPUT); digitalWrite(RELAY, LOW); // 连接WiFi Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED){ delay(500); Serial.print("."); } Serial.println("\nServer - WiFi connected"); // 启动服务器 server.begin(); Serial.println("Server started"); Serial.print("Use this IP to connect: "); Serial.println(WiFi.localIP()); } void loop() { // 使用server.accept()获取新连接的客户端 WiFiClient client = server.accept(); if (client) { Serial.println("New client connected"); // 等待客户端发送数据(最多1秒) int nr_of_tries = 1000; while(!client.available() && nr_of_tries > 0) { nr_of_tries--; delay(1); } if (client.available()) { uint8_t buffer[Protocol::BUFFER_SIZE]; int len = client.read(buffer, Protocol::BUFFER_SIZE); int pinNumber = buffer[Protocol::PIN]; int value = buffer[Protocol::VALUE]; Serial.print("Pin Number: "); Serial.println(pinNumber); Serial.print("Value: "); Serial.println(value); if (pinNumber == RELAY) { pinMode(pinNumber, OUTPUT); digitalWrite(pinNumber, value); } // 关键修正:通过client对象发送回复,而非server size_t sendLen; if (value == 0) { sendLen = client.println("Set"); } else { sendLen = client.println("Reset"); } Serial.print("Sent bytes: "); Serial.println(sendLen); // 确保数据发送完成 client.flush(); } // 关闭客户端连接 client.stop(); Serial.println("Client disconnected"); } }
客户端代码(微调优化)
int pin_value = 0; uint8_t ip[4] = {10, 0, 0, 6}; void setup() { Serial.begin(115200); // 连接WiFi Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED){ delay(500); Serial.print("."); } Serial.println("\nClient - WiFi connected"); } void loop(){ WiFiClient client; if (!client.connect(ip, SERVER_PORT)){ Serial.println("Failed to connect to server"); delay(1000); return; } uint8_t buffer[Protocol::BUFFER_SIZE]; buffer[Protocol::PIN] = RELAY; buffer[Protocol::VALUE] = pin_value; client.write(buffer, Protocol::BUFFER_SIZE); client.flush(); // 确保数据发送完成 // 等待服务器回复(最多10秒) int nr_of_tries = 10000; String response = ""; while (client.connected() && nr_of_tries > 0) { if (client.available()) { response = client.readStringUntil('\n'); nr_of_tries = 0; Serial.print("Server response: "); Serial.println(response); } else { delay(1); nr_of_tries--; } } Serial.print("Remaining tries: "); Serial.println(nr_of_tries); Serial.print("Client connected: "); Serial.println(client.connected()); client.stop(); Serial.println("Request completed"); // 切换引脚值 pin_value = (pin_value == 0) ? 1 : 0; Serial.print("Pin_value set to: "); Serial.println(pin_value); delay(10000); }
server.accept()使用示例
以下是server.accept()的基础用法,用于处理新的客户端连接:
WiFiServer server(5000); void setup() { server.begin(); } void loop() { // 获取新连接的客户端 WiFiClient client = server.accept(); if (client) { Serial.println("New client connected"); // 读取客户端数据 while (client.available()) { char c = client.read(); Serial.print(c); } // 发送回复 client.println("Hello from server"); client.flush(); // 关闭连接 client.stop(); Serial.println("Client disconnected"); } }
内容的提问来源于stack exchange,提问作者ToniE
相关产品推荐
相关产品推荐

