Implementing Socket.io Server with node-red-contrib-socketio-server

Hello everyone,

I am trying to implement a Socket.io Server within NodeRed with node-red-contrib-socketio-server on NodeRed v2.2.2

In my simple test setup the following works:

  • Connect to server instance on port i.e. 3000
  • Receiving a "connection" event at client connected
  • Sending a custom event "/test/status" after client connected.

What does not work is receiving other events than "connection" such as a custom event "heartbeat". I also tried to send "/heartbeat" and giving a namespace such as "test/heartbeat" when sending from Postman. I did not alter any of the default connection settings (i.e. handshake path) of the socket.io connection other than the version to v4.

This is the test flow:

[{"id":"28133897f32ae0ec","type":"socket.io-on","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"heartbeat","namespace":"","x":140,"y":320,"wires":[["8a19fa443749dd1e"]]},{"id":"25ea63e17bc72abf","type":"socket.io-on","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"connection","namespace":"","x":140,"y":220,"wires":[["691bac9209ec91c4"]]},{"id":"9873ca4d1cc7b5f9","type":"socket.io-emit","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/status","namespace":"","room":"","x":560,"y":220,"wires":[]},{"id":"691bac9209ec91c4","type":"change","z":"de35f1b4ffe0c443","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"Connection: Test worked.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":220,"wires":[["9873ca4d1cc7b5f9"]]},{"id":"3187e0ab59da7b80","type":"socket.io-emit","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/status","namespace":"","room":"","x":560,"y":320,"wires":[]},{"id":"8a19fa443749dd1e","type":"change","z":"de35f1b4ffe0c443","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"heartbeat: Test worked.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":320,"wires":[["3187e0ab59da7b80"]]},{"id":"578ee58bda22c2b9","type":"socket.io-on","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/heartbeat","namespace":"","x":140,"y":380,"wires":[["71547f8c6e58ee38"]]},{"id":"cbfa8dc0fc6d8327","type":"socket.io-emit","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/status","namespace":"","room":"","x":560,"y":380,"wires":[]},{"id":"71547f8c6e58ee38","type":"change","z":"de35f1b4ffe0c443","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"/heartbeat: Test worked.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":380,"wires":[["cbfa8dc0fc6d8327"]]},{"id":"f596dd7707d9034d","type":"socket.io-on","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/heartbeat","namespace":"","x":150,"y":440,"wires":[["8337e5299c8b9d1d"]]},{"id":"2cff4ef0d7a258c4","type":"socket.io-emit","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/status","namespace":"","room":"","x":560,"y":440,"wires":[]},{"id":"8337e5299c8b9d1d","type":"change","z":"de35f1b4ffe0c443","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"/test/heartbeat: Test worked.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":440,"wires":[["2cff4ef0d7a258c4"]]},{"id":"8752620ca507e96d","type":"socket.io-on","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"test/heartbeat","namespace":"","x":150,"y":500,"wires":[["b7b8dd59c7eb6e38"]]},{"id":"07f2e451c6a3c28c","type":"socket.io-emit","z":"de35f1b4ffe0c443","name":"","instance":"92b487130561dda4","event":"/test/status","namespace":"","room":"","x":560,"y":500,"wires":[]},{"id":"b7b8dd59c7eb6e38","type":"change","z":"de35f1b4ffe0c443","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"test/heartbeat: Test worked.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":500,"wires":[["07f2e451c6a3c28c"]]},{"id":"92b487130561dda4","type":"socket.io-instance","name":"","bindToNode":false,"port":"3000","options":"{\n    \"cors\": {\n        \"origin\": \"*\",\n        \"credentials\": false\n    }\n}"}]

This is what the Postman side looks like: Postman screenshot

Has anyone successfully implemented a socket.io server instance in NodeRed and could give me some hints please how to listen on events properly?

Any help is much appreciated!

Hi, probably not what you are looking for but uibuilder implements its own Socket.IO server. All of the code is in a separate library. If nothing else, it may give you an idea about what events do what.

Maybe if you were to describe more of what you want to achieve, there might be other ways of doing it?

Thanks for the hint! I will take a look at uibuilder to use it's socket-io server. Do you think it would be possible to connect with a client from within NodeRed to the uibuilder-Socket.io-Server? What port is it actually on?

I need to exchange realtime messages (JSON-Objects) with a given frontend website. The website uses Socket.io so this is what I have to implement on NodeRed-side as well.

Certainly. You would need to use the Socket.IO client library and understand the namespace setup that uibuilder uses. You can look at the front-end library (currently uibuilderfe.js, a new client is in the works) to see how the client end of things works.

Though I probably would ask why? Because there are already ways of communicating between node-red instances without needing Socket.IO.

The problem is: The front end website I need to communicate with is not another node-red instance but is hosted on another webserver. The website is displayed though on the machine I run node-red on.

Do you need a socket io server for this ?
websocket nodes are already installed out of the box. You can connect to a websocket and send data to the websocket.

Raw Websockets were my initial approach as well. And they worked out-of-the-box.

The developer of the front end has a problem with the websocket implementation, as I can only define one path per socket connection (at least to my knowledge - please correct me on that!). Therefore he states he has to implement several connections (one for each path) which undermines the usage of sockets.

OK, we seem to now be straying from the original question. That's OK but shows why we need to understand what you need to achieve.

It is important to note that Socket.IO is NOT websockets. Yes, it uses websockets as one of its possible transport mechanisms but you cannot use Socket.IO to talk direct to websockets, you have to use the Socket.IO client.

If the front-end can be amended, then you can open multiple websocket connections to get multiple channels though that isn't very scalable I don't think. Some of the advantages of Socket.IO are that it allows multiple namespaces, rooms, etc. It also supports things like reconnection processing and binary data transfers to mention a few. More importantly, it has the option of fallback transport methods for cases where websockets isn't reliable or is not permitted through firewalls.

Not sure if this helps but it is certainly possible to use the uibuilder client library with a web site served outside of Node-RED as well. The client library works with the Socket.IO client and handles all the complexities of creating a namespaced connection back to a uibuilder node in node-red.

1 Like

You are correct. Initially I am trying to get going with a socket.io-server implementation in node-red. I am a bloody beginner in using sockets fĂĽr communication as you might have already noticed =)

Therefore maybe somebody could take heart and set up my simple test project and try to talk to the node-red implemented socket.io-server using i. e. Postman.

I'd be infinitely grateful.

PS: I am using SSL secured node-red. Could that be part of the problem?

Ah, well here is your issue! As I said, Socket.IO only uses websockets as one of its transports. You can't use postman because (as far as I know), it doesn't understand Socket.IO comms. Only raw websockets.

Now, Socket.IO does have a monitoring server I believe but I've not had time to try it out as yet so I don't know how useful nor how complex it might be.

I think that we need to take a slight step back because we are very close to the issue here but not necessarily all that close to the requirement.

As I understand it, you need to exchange messages between Node-RED and a website. I guess what I haven't asked is whether you can connect direct to the website's socket.io SERVER? Because I've been thinking about client connections. So what does the server expose? and how are you wanting to connect? Lets come back to the socket.io question after I understand this.

Thanks for your time, TotallyInformation!

As far as I know does Postman have a beta-feature "Socket.io"-connection. But I know to little to comment on how it is implemented. https://blog.postman.com/postman-now-supports-socket-io/

The plan was to set up a server on the node-red side and to connect with the website to it.

Without wanting to get off-topic again just a quick status of the project to take out pressure =)
We have found a work-around using websocket again only with one connection:
The website connects to only one endpoint and sends a topic together with each payload. Node-Red switches according to the topic. Likewise node-red responds to the very same endpoint with a topic set accordingly.
Basically we trade "events" with "topics".

I do not want to close the issue, as the initial question remains and maybe somebody who has implemented this with socket.io-server ( node-red-contrib-socketio-server in node-red stumbles in.

You can setup multiple websocket endpoints if that is the question:

And that was going to be my next suggestion but needed to understand the Socket.IO connection more as that seemed to be the direction you wanted.

Ah, OK, didn't know that :slight_smile: Personally, I don't use it.

You mentioned SSL but that shouldn't be a problem as long as Socket.IO is set up correctly. I use it with uibuilder and it just works, you simply have to connect the Socket.IO server to an https server instead of an http one. Nothing really to do on the client except make sure you are using the correct PATH and NAMESPACE (and ROOM if you are using them).

It is, of course, possible that your web server requires some authentication information, we didn't talk about that. Because Socket.IO uses an ExpressJS connection, it will need the same authorisation.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.