Electron 网络与外部通信

Electron 应用不仅可以操作本地资源,也可以与外部网络服务进行交互。
无论是发起 HTTP 请求、建立实时 WebSocket 连接,还是使用 Node.js 的原生 net 模块,你都可以像在浏览器或服务器上一样进行网络通信。


HTTP 请求

Electron 同时支持 浏览器 API(fetch)第三方库(axios),并且可以处理跨域与认证问题。


fetch API 使用

fetch 是现代浏览器与 Node.js(18+)内置的网络请求接口。
它支持 Promise,语法简洁,适合常规数据请求。

实例

// GET 请求示例
fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(response => {
    if (!response.ok) throw new Error('网络响应错误');
    return response.json();
  })
  .then(data => {
    console.log('返回数据:', data);
  })
  .catch(error => {
    console.error('请求失败:', error);
  });

参数说明:

  • fetch(url, options):发起请求;
  • options.method:请求方式(GET、POST、PUT、DELETE);
  • options.headers:设置请求头;
  • options.body:请求体,POST 时常用。

POST 示例:

fetch('https://api.example.com/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'admin', password: '123456' })
});

axios 集成

axios 是一个功能强大的 HTTP 客户端,支持拦截器、超时、并发等特性,常用于 Electron 应用中与后端 API 通信。

安装:

npm install axios

使用示例:

const axios = require('axios');

// GET 请求
axios.get('https://jsonplaceholder.typicode.com/users')
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

// POST 请求
axios.post('https://api.example.com/data', { name: 'Tom' })
  .then(res => console.log('上传成功', res.data))
  .catch(err => console.error('上传失败', err));

参数说明:

  • axios.get(url, config):发起 GET 请求;
  • axios.post(url, data, config):发起 POST 请求;
  • config.timeout:设置超时时间;
  • config.headers:自定义请求头。

处理跨域问题

在 Electron 中,因为运行在桌面环境,默认不存在浏览器的 CORS 限制
但如果前端页面通过 BrowserWindow 加载网页内容并发请求,仍可能触发跨域问题。

解决方案:

使用 nodeIntegration
在主进程中发起请求而不是渲染进程。

const { ipcMain } = require('electron');
const axios = require('axios');

ipcMain.handle('getData', async () => {
  const res = await axios.get('https://api.example.com/data');
  return res.data;
});

通过 session.webRequest 修改请求头:

const { session } = require('electron');
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
  details.requestHeaders['Origin'] = '*';
  callback({ requestHeaders: details.requestHeaders });
});

WebSocket 通信

WebSocket 提供持久化、全双工的实时通信通道,非常适合用于聊天、数据推送、股票行情等应用。

WebSocket 客户端实现

Electron 可以直接使用浏览器原生的 WebSocket API:

实例

const socket = new WebSocket('wss://echo.websocket.org');

socket.onopen = () => {
  console.log('WebSocket 连接已建立');
  socket.send('Hello Server!');
};

socket.onmessage = (event) => {
  console.log('收到消息:', event.data);
};

socket.onclose = () => {
  console.log('连接已关闭');
};

参数说明:

  • new WebSocket(url):创建连接;
  • socket.send(data):发送消息;
  • onmessage:监听服务器返回;
  • onclose:监听连接关闭。

实时通信应用示例

假设我们构建一个实时聊天室界面:

实例

const socket = new WebSocket('wss://chat.example.com');

socket.onmessage = (e) => {
  const messageBox = document.getElementById('messages');
  messageBox.innerHTML += `<div>${e.data}</div>`;
};

function sendMessage() {
  const input = document.getElementById('input');
  socket.send(input.value);
  input.value = '';
}

渲染进程的 HTML:

实例

<input id="input" placeholder="输入消息">
<button onclick="sendMessage()">发送</button>
<div id="messages"></div>

这种模式可以轻松实现实时聊天、状态同步、协同编辑等功能。


原生网络模块

Electron 的主进程提供了 Node.js 的 net 模块,可以在更底层直接创建 TCP 或 IPC 连接,适用于定制化协议或本地服务交互。

net 模块使用

net 模块允许你创建 TCP 客户端或服务器。

创建 TCP 服务器:

实例

const net = require('net');

const server = net.createServer(socket => {
  console.log('客户端已连接');
  socket.write('欢迎来到 Electron TCP 服务器');
 
  socket.on('data', data => {
    console.log('收到数据:', data.toString());
  });
});

server.listen(8080, () => {
  console.log('TCP 服务器已启动,端口 8080');
});

TCP 客户端连接:

实例

const client = net.createConnection({ port: 8080 }, () => {
  console.log('已连接到服务器');
  client.write('Hello Server!');
});

client.on('data', data => {
  console.log('服务器响应:', data.toString());
});

参数说明:

  • net.createServer(callback):创建服务器;
  • socket.write(data):发送数据;
  • socket.on('data'):接收数据;
  • server.listen(port):监听端口。

session 管理

Electron 中的 session 模块可控制缓存、Cookie、代理等网络会话信息。

实例

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

const ses = session.defaultSession;

// 清除缓存
ses.clearCache().then(() => console.log('缓存已清除'));

// 设置代理
ses.setProxy({ proxyRules: 'http=127.0.0.1:8080' });

Cookie 处理

实例

const { session } = require('electron');
const cookies = session.defaultSession.cookies;

// 设置 Cookie
cookies.set({
  url: 'https://example.com',
  name: 'token',
  value: 'abc123',
  expirationDate: Date.now() / 1000 + 3600
});

// 获取 Cookie
cookies.get({ url: 'https://example.com' })
  .then(cookies => {
    console.log('当前 Cookie:', cookies);
  });

小结

在 Electron 中进行网络与外部通信时,可以灵活选择:

场景 推荐方案
普通 HTTP 请求 fetch 或 axios
实时数据 WebSocket
本地或底层通信 net 模块
管理登录状态 / 缓存 session + cookies

这种多层级的网络能力,让 Electron 应用既能访问云端 API,也能与本地服务协同运行。


实例

以下实例是一个简洁的"实时数据仪表盘",可以在渲染进程显示从 API 获取的数据,并实时接收 WebSocket 消息,同时管理登录状态 Cookie。

一、项目结构

my-electron-network-demo/
├── package.json
├── main.js             # 主进程逻辑
├── preload.js          # 预加载脚本
└── index.html          # 前端界面

二、package.json

{
  "name": "my-electron-network-demo",
  "version": "1.0.0",
  "description": "Electron 网络通信综合示例",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": "latest",
    "axios": "^1.5.0"
  }
}

安装依赖:

npm install

三、main.js(主进程)

实例

const { app, BrowserWindow, ipcMain, session } = require('electron')
const path = require('path')
const axios = require('axios')
const WebSocket = require('ws')

let mainWindow

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 900,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadFile('index.html')
}

// HTTP 请求示例
ipcMain.handle('fetch-data', async () => {
  try {
    const res = await axios.get('https://jsonplaceholder.typicode.com/posts/1')
    return res.data
  } catch (err) {
    return { error: err.message }
  }
})

// WebSocket 服务器示例
const wss = new WebSocket.Server({ port: 8081 })
wss.on('connection', ws => {
  console.log('客户端已连接 WebSocket')
  ws.send('欢迎连接 WebSocket 实时数据')
  // 定时推送数据
  const interval = setInterval(() => {
    ws.send(`实时消息:${new Date().toLocaleTimeString()}`)
  }, 3000)

  ws.on('close', () => clearInterval(interval))
})

// WebSocket 消息转发给渲染进程
ipcMain.handle('connect-ws', async () => {
  return new Promise(resolve => {
    const ws = new WebSocket('ws://localhost:8081')
    ws.on('open', () => console.log('已连接到 WebSocket 服务器'))
    ws.on('message', msg => {
      mainWindow.webContents.send('ws-message', msg.toString())
    })
    resolve('WebSocket 连接已建立')
  })
})

// Cookie 管理示例
ipcMain.handle('set-cookie', async (event, name, value) => {
  const cookies = session.defaultSession.cookies
  await cookies.set({
    url: 'http://localhost',
    name,
    value,
    expirationDate: Date.now() / 1000 + 3600
  })
  return 'Cookie 设置成功'
})

ipcMain.handle('get-cookie', async (event, name) => {
  const cookies = session.defaultSession.cookies
  const result = await cookies.get({ url: 'http://localhost', name })
  return result.length ? result[0].value : null
})

app.whenReady().then(() => {
  createWindow()
})

四、preload.js(安全通信)

实例

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  fetchData: () => ipcRenderer.invoke('fetch-data'),
  connectWS: () => ipcRenderer.invoke('connect-ws'),
  onWSMessage: (callback) => ipcRenderer.on('ws-message', (event, msg) => callback(msg)),
  setCookie: (name, value) => ipcRenderer.invoke('set-cookie', name, value),
  getCookie: (name) => ipcRenderer.invoke('get-cookie', name)
})

五、index.html(渲染进程界面)

实例

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Electron 网络通信示例</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    button { margin: 5px; padding: 10px 20px; cursor: pointer; }
    #output { margin-top: 20px; }
  </style>
</head>
<body>
  <h1>Electron 网络通信示例</h1>

  <button id="fetchBtn">获取 HTTP 数据</button>
  <button id="wsBtn">连接 WebSocket</button>
  <button id="setCookieBtn">设置 Cookie</button>
  <button id="getCookieBtn">读取 Cookie</button>

  <div id="output"></div>

  <script>
    const output = document.getElementById('output')

    document.getElementById('fetchBtn').addEventListener('click', async () => {
      const data = await window.electronAPI.fetchData()
      output.innerHTML += `<p>HTTP 返回数据:${JSON.stringify(data)}</p>`
    })

    document.getElementById('wsBtn').addEventListener('click', async () => {
      await window.electronAPI.connectWS()
      output.innerHTML += `<p>WebSocket 连接已建立</p>`
    })

    window.electronAPI.onWSMessage(msg => {
      output.innerHTML += `<p>WebSocket 消息:${msg}</p>`
    })

    document.getElementById('setCookieBtn').addEventListener('click', async () => {
      const res = await window.electronAPI.setCookie('token', 'abc123')
      output.innerHTML += `<p>${res}</p>`
    })

    document.getElementById('getCookieBtn').addEventListener('click', async () => {
      const value = await window.electronAPI.getCookie('token')
      output.innerHTML += `<p>Cookie token 值:${value}</p>`
    })
  </script>
</body>
</html>

六、运行与效果

npm start
  • 点击 获取 HTTP 数据:通过 axios 获取 API 数据并显示在页面上。
  • 点击 连接 WebSocket:建立实时连接,每 3 秒接收一条消息。
  • 点击 设置 Cookie:创建 token Cookie。
  • 点击 读取 Cookie:读取并显示 token 值。