电子:socket.io可以接收但不发射

时间:2017-06-06 08:23:02

标签: node.js socket.io electron

我正在创建一个使用Socket.io与服务器应用程序通信的Electron应用程序,但我遇到了一个奇怪的问题:我的Electron应用程序成功加入并接收来自我的服务器的消息,它完全是没有发射任何东西。

客户端:

const io = require('socket.io-client');
// ...
var socket = io("http://localhost:8081");

socket.on('welcome', () => {
  console.log('welcome received'); // displayed
  socket.emit('test')
});
socket.on('error', (e) => {
  console.log(e); // not displayed
});
socket.on('ok', () => {
  console.log("OK received"); // not displayed
});
socket.on('connect', () => {
  console.log("connected"); // displayed
  socket.emit('test');
});

服务器侧

io.on('connection', (client) => {
  io.emit('welcome');

  client.on("test", () => {
      console.log("received test"); // not displayed
      io.emit("ok");
  })
});
io.listen(8081);

请注意,还有一个连接到服务器的Web客户端,并且按预期工作。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

Electron的主进程可以具有节点集成功能,而渲染器进程则出于安全原因而默认关闭了nodeIntegration

如果您尝试在主进程(main.js)中使用客户端代码,它将正常工作并正常接收/发送。但是,如果您尝试在渲染过程中使用客户端代码,则它将无法正常工作。您需要在preload.js内添加客户端代码,然后使用BrowserWindow的{​​{3}}选项预先加载客户端代码,如下所示:

function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')
  ...
}

然后您可以在preload.js中包含客户端代码:

const io = require('socket.io-client');
const socket = io(`http://localhost:${process.env.SOCKET_PORT}`);

socket.on('welcome', () => {
  console.log('on welcome : welcome received renderer'); // displayed
  socket.emit('test')
});
socket.on('error', (e) => {
  console.log(e); // displayed ?
});
socket.on('ok', () => {
  console.log("OK received renderer"); // displayed
});
socket.on('connect', () => {
  console.log("connected renderer"); // displayed
  socket.emit('test');
});

从插座开始,启动电子应用程序并查看其工作情况:

套接字服务器:

webPreferences.preload

应用程序控制台:

socket.io server

当心Electron app

Content Security Policy (CSP)

为避免这种情况,您必须将WS服务器添加到CSP中。对于本地主机,请在index.html标头中使用此符号:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' ws://localhost:*/socket.io/; script-src 'self' ws://localhost:*/socket.io/">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self' ws://localhost:*/socket.io/; script-src 'self' ws://localhost:*/socket.io/">

这是所有端口的本地主机服务器,当然,它仅用于开发,您必须在生产中输入普通的WS服务器。

您可以从Github克隆并检查我的工作示例:Content Security Policy error

编辑 最后但并非最不重要的;检查并允许在firewal中对nodejs和/或端口进行传入/传出访问。

Electron version: 7.1.2
Node version: 12.8.1