【解决方案】 Electron 中调用 IP 话机接口的 ECONNRESET 错误

44 阅读1分钟

在 Electron 主进程中发起 HTTP 请求访问 IP 话机接口:

fetch(`http://${phoneActionIp}/xxxx/sanshi.com?key=${key}`, {
  method: 'GET',
  headers: {
    Authorization: 'Basic ' + Buffer.from('admin:admin').toString('base64'),
  }
})

短时间内连续请求多次时,接口报错:

image-20251104190551941.png

问题原因

Node 的 fetch 默认使用 HTTP Keep-Alive 长连接机制,重用之前的 TCP 连接从而提高性能;

而 IP 话机上的 HTTP 服务一般是嵌入式 CGI 服务器(如 boa、thttpd、microhttpd),这些服务一般只实现了 HTTP/1.0 或非常简化的 1.1,不支持复用 TCP 连接,每次响应后立即 close

触发流程

请求1完成后: Node 保留 TCP 连接在连接池中,话机的服务端却已经关闭了 socket。

请求2时: Node 尝试复用“已关闭”的 TCP 连接,这时已经连接不到话机服务器了,话机返回 TCP RST(Rest) 包,Node 抛出 ECONNRESET。

解决方案

定义请求头中 Connection 属性为 close,表示请求完成后主动关闭连接,下次重新建立新的 TCP。

fetch(url, {
  headers: {
    Connection: 'close'
  }