Electron: socket.io can receive but not emit

℡╲_俬逩灬. 提交于 2021-02-05 20:16:10

问题


I'm creating an Electron application that uses Socket.io to communicate to a server application, but I'm experiencing a weird issue: whereas my Electron app successfully joins and receives messages from my server, it completely fails to emit anything.

Client-side:

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');
});

Server-side:

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

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

Note that there is also a Web client that connects to the server, and works absolutely as expected.

What am I doing wrong?


回答1:


Electron has the main process that can have node integration and renderer process that has nodeIntegration turned off by default for security reasons.

If you try to use your client code in the main process (main.js) it will work and receive/emit normal. But if you try to use the client code on the rendered process, then it won't work. You need to add the client code inside the preload.js and then preload it using the webPreferences.preload option of the BrowserWindow like this:

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')
  ...
}

Then you can have the client code inside 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');
});

begin the socket, start the electron app and see it working:

Socket server:

App console:

Beware of the Content Security Policy (CSP):

To avoid this, you have to add your WS server to your CSP. For localhost use this inside index.html header:

<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/">

It's a localhost server for all ports and of course it's for development only, you have to enter normal WS server in production.

You can clone and check my working example from Github: https://github.com/clytras/electron-sockets

EDIT Last but not least; check and allow incomming/outgoing access for nodejs and/or port in firewal.

Electron version: 7.1.2
Node version: 12.8.1


来源:https://stackoverflow.com/questions/44384902/electron-socket-io-can-receive-but-not-emit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!