WiFi连接ESP8266时出现ERR_CONNECTION_REFUSED错误的原因排查
问题场景
你上传了这段ESP8266代码后,遇到了一个奇怪的现象:笔记本通过LAN有线连接网络时,和ESP8266通信完全正常;但用手机或笔记本通过WiFi连接时,频繁弹出ERR_CONNECTION_REFUSED错误,只有偶尔能成功通信。你已经排查了设备更换、路由器重置,也确认了AP隔离处于禁用状态,那问题可能出在哪呢?
先贴出你的代码方便分析:
#include <ESP8266WiFi.h> const char* ssid = "*****"; const char* password = "*******"; WiFiServer server(80); void setup() { Serial.begin(115200); Serial.println(); Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(" connected"); server.begin(); Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str()); } // prepare a web page to be send to a client (web browser) // the connection will be closed after completion of the response // the page will be refreshed automatically every 5 sec String prepareHtmlPage() { String htmlPage = String("HTTP/1.1 200 OK\r\n") + "Content-Type: text/html\r\n" + "Connection: close\r\n" + "Refresh: 5\r\n" + "\r\n" + "<!DOCTYPE HTML>" + "<html>" + "Analog input: " + String(analogRead(A0)) + "</html>" + "\r\n"; return htmlPage; } void loop() { WiFiClient client = server.available(); // wait for a client (web browser) to connect if (client) { Serial.println("\n[Client connected]"); while (client.connected()) { // read line by line what the client (web browser) is requesting if (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); // wait for end of client's request, that is marked with an empty line if (line.length() == 1 && line[0] == '\n') { client.println(prepareHtmlPage()); break; } } } delay(1); // give the web browser time to receive the data // close the connection: client.stop(); Serial.println("[Client disconnected]"); } }
可能的原因与优化方案
1. 无线环境下的请求处理超时逻辑缺失
你的代码在处理客户端连接时,没有设置超时机制。WiFi无线环境本身容易出现信号波动、丢包,导致客户端的请求数据包延迟到达。如果ESP8266一直卡在while(client.connected())的循环里等待数据,后续的新连接请求就会被拒绝,表现为频繁的连接失败。
优化方案:给客户端连接增加超时限制,比如5秒内没收到完整请求就主动关闭连接,释放资源给新请求:
void loop() { WiFiClient client = server.available(); if (client) { Serial.println("\n[Client connected]"); unsigned long timeout = millis(); // 设置5秒超时,避免无限等待 while (client.connected() && millis() - timeout < 5000) { if (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); // 更健壮的空行判断(兼容不同客户端的换行格式) if (line.trim().isEmpty()) { client.println(prepareHtmlPage()); client.flush(); // 等待所有数据发送完成 break; } timeout = millis(); // 每次收到数据就刷新超时时间 } } client.stop(); Serial.println("[Client disconnected]"); } }
2. 连接关闭时机过于仓促
代码里用delay(1)来给浏览器时间接收数据,但1ms在无线环境下完全不够——无线数据传输的延迟远高于有线,ESP8266可能还没把所有数据发送出去就关闭了连接,客户端那边就会触发连接拒绝的错误。
优化方案:用client.flush()替代delay(1),这个函数会阻塞直到所有数据都发送完毕,比固定延迟更可靠。
3. WiFi重连后的服务器状态问题
虽然你的setup里启动了服务器,但如果ESP8266运行过程中因为无线信号波动短暂掉线又重连,服务器可能无法自动恢复监听(虽然大部分情况ESP8266的WiFiServer会自动处理,但不是100%可靠)。另外,如果重连后IP地址变化了,客户端用旧IP访问也会失败,但你说偶尔能成功,这个概率较低,但可以做个兜底检查。
优化方案:在loop里定期检查WiFi状态,如果断开重连后重新启动服务器:
void loop() { // 检查WiFi连接状态,断开则重连并重启服务器 if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi disconnected, reconnecting..."); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Reconnected!"); server.begin(); // 重启服务器 Serial.printf("Server restarted, new IP: %s\n", WiFi.localIP().toString().c_str()); } // 原有客户端处理逻辑... }
4. 路由器信道干扰
无线环境中,路由器的信道选择也会影响连接稳定性。如果周围有很多WiFi设备用了重叠信道(比如2-5信道),会导致严重的干扰,ESP8266和客户端之间的数据包丢包率飙升,进而触发连接拒绝。
优化方案:登录路由器后台,把WiFi信道固定为1、6、11这三个非重叠信道中的一个,减少干扰。
内容的提问来源于stack exchange,提问作者Shalabyer




