You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron中单例WebSocket客户端的最佳放置位置及实现示例

Electron单例WebSocket客户端实现方案

最佳放置位置

直接放在**主进程(Main Process)**里是最优选择:

  • 主进程本身就是单例运行,天然保证WebSocket客户端不会重复创建
  • 主进程可直接访问Node.js API,方便写入本地存储(不管是用fs模块还是Electron官方的electron-store)
  • 主进程和渲染进程通过IPC通信,既能把WebSocket收到的消息推给渲染进程,也能接收渲染进程的指令发送消息

核心实现思路

  1. 在主进程启动时初始化WebSocket客户端,做单例校验
  2. 监听WebSocket的message事件,收到数据后直接写入本地存储
  3. 主进程注册IPC监听,接收渲染进程的发送消息请求,转发给WebSocket服务器
  4. 实现基础的重连逻辑,避免连接断开后无法恢复

完整代码示例

主进程代码(main.js)

const { app, BrowserWindow, ipcMain } = require('electron');
const Store = require('electron-store'); // 用electron-store做结构化本地存储,也可替换为fs模块
const WebSocket = require('ws');

// 初始化本地存储实例
const store = new Store();

// 单例WebSocket客户端实例
let wsClient = null;
const WS_SERVER_URL = 'ws://your-server-address:port';

// 创建/重建WebSocket连接的方法
function initWebSocket() {
  // 如果已有活跃连接,直接返回
  if (wsClient?.readyState === WebSocket.OPEN) return;

  wsClient = new WebSocket(WS_SERVER_URL);

  // 连接成功回调
  wsClient.on('open', () => {
    console.log('WebSocket连接已建立');
  });

  // 接收服务器消息并写入本地存储
  wsClient.on('message', (rawData) => {
    const message = JSON.parse(rawData.toString());
    console.log('收到服务器消息:', message);
    // 按时间戳存储消息,避免覆盖
    store.set(`ws_msg_${Date.now()}`, message);
    // 同步推送给所有打开的渲染窗口
    BrowserWindow.getAllWindows().forEach(window => {
      window.webContents.send('ws-incoming-message', message);
    });
  });

  // 连接断开后自动重连
  wsClient.on('close', () => {
    console.log('WebSocket连接断开,5秒后尝试重连');
    setTimeout(initWebSocket, 5000);
  });

  // 连接错误处理
  wsClient.on('error', (err) => {
    console.error('WebSocket连接出错:', err);
  });
}

// 创建应用窗口
function createMainWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 实际项目建议开启contextIsolation,用contextBridge暴露IPC方法
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');
}

// 应用就绪后初始化WebSocket和窗口
app.whenReady().then(() => {
  initWebSocket();
  createMainWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createMainWindow();
  });
});

// IPC监听:接收渲染进程的消息发送请求
ipcMain.on('ws-send-message', (event, payload) => {
  if (wsClient?.readyState === WebSocket.OPEN) {
    wsClient.send(JSON.stringify(payload));
    console.log('已发送消息到服务器:', payload);
  } else {
    event.reply('ws-send-fail', 'WebSocket未连接');
    console.error('WebSocket未连接,无法发送消息');
  }
});

// 关闭所有窗口时退出应用(macOS除外)
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

渲染进程代码(renderer.js)

const { ipcRenderer } = require('electron');

// 监听主进程推送的WebSocket消息
ipcRenderer.on('ws-incoming-message', (event, message) => {
  console.log('渲染进程收到消息:', message);
  // 更新页面显示
  const messageList = document.getElementById('message-list');
  messageList.innerHTML += `<div class="message-item">${JSON.stringify(message)}</div>`;
});

// 发送消息到服务器的方法
function sendMessage() {
  const input = document.getElementById('msg-input');
  const content = input.value.trim();
  if (!content) return;

  const payload = {
    content,
    sendTime: Date.now()
  };

  ipcRenderer.send('ws-send-message', payload);
  
  // 监听发送失败的反馈
  ipcRenderer.once('ws-send-fail', (event, errMsg) => {
    alert(`发送失败:${errMsg}`);
  });

  input.value = '';
}

页面示例(index.html)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>WebSocket客户端</title>
  <style>
    .message-item { margin: 8px 0; padding: 8px; border-bottom: 1px solid #eee; }
  </style>
</head>
<body>
  <div id="message-list"></div>
  <div style="margin-top: 20px;">
    <input type="text" id="msg-input" placeholder="输入消息内容" style="width: 600px; padding: 6px;">
    <button onclick="sendMessage()" style="padding: 6px 12px;">发送</button>
  </div>
  <script src="./renderer.js"></script>
</body>
</html>

注意事项

  • 本地存储选择:electron-store适合结构化数据存储,自动处理JSON序列化;如果是大文件存储,建议用fs模块
  • 重连优化:示例用固定间隔重连,实际可改为指数退避策略(比如第一次5秒,第二次10秒,最大间隔60秒)
  • 安全规范:生产环境建议开启contextIsolation,通过contextBridge暴露IPC方法,避免渲染进程直接访问Node.js API
  • 资源清理:应用退出前可主动调用wsClient.close()关闭WebSocket连接,避免残留连接

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:20:31