You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WiFi连接ESP8266时出现ERR_CONNECTION_REFUSED错误的原因排查

ESP8266 WiFi连接时频繁出现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

火山引擎 最新活动