Is it possible to both listen and send messages to a remote socket using node-red's websocket node? - node.js

The Almond Plus router and home automation hub now exposes the state of its registered z-wave and zigbee sensors via a websocket.
The websocket API is here:
https://wiki.securifi.com/index.php/Websockets_Documentation
I've aimed a node-red websocket node at the router's local IP address, and have included authentication information in the URL. This seems to work for receiving status changes to devices.
But I need to also be able to send commands over the websocket to flip switches and whatnot. When I create both 'listen on' and 'connect to' websocket nodes in node-red, only the node that's listening connects. Do I need to make two nodes at all? I would have hoped there'd be a way to make one connection to the websocket and use it for two-way communication, but maybe this question just exposes my ignorance of how either websockets or node-red function.
Thanks for any help or information.

You should need both a Websocket in and a Websocket out, but both should be set to "connect to" mode. These handle the input and output side of the connection
I'd have to double check the code, but they should share the same client connection under the covers so there will only be one real Websocket connection. But even if the 2 nodes don't share the connection having 2 separate websocket connections to the same address shouldn't be a problem.

Related

How to create a nodejs HTTP server with an existing TLS client socket?

I have a nodejs TLS client socket on my laptop, connected to a TLS server socket on a different computer (server). The server cannot connect to my laptop. The laptop needs to initiate the connection.
Now I want the server to make requests to my laptop. The idea is to reuse the HTTP protocol. Is there a way to create a HTTP server using the existing TLS client socket?
This way, the server machine can make a HTTP request, and the client TLS receives it, and the HTTP server would parse it? Or am I missing something?
Once you have a TCP socket open between laptop and server, you can send data either way over that socket. So, if the server wants to send some query to the laptop, it can do so just fine. You will have to invent your own protocol on top of TCP to do that, but it could be as simple as a text/line based protocol if you want.
Or, instead of making a plain TCP connection, you can make a webSocket or socket.io connection from the laptop to the server (instead of the plain TCP connection) and then either side can send messages either way and the protocol part is already taken care of. If you use socket.io, it will automatically reconnect if the connection is interrupted too.
There is no simple way to attach an HTTP server to an existing TCP socket and it would be fraught with difficulties too because an HTTP connection is generally not a continuous connection over which you send many separate requests (advanced versions of http can do that, but I doubt you want to get into implementing all that logic on both ends). You could use the HTTP protocol over your existing TCP socket, but that would probably be substantially more work to implement than just use the webSocket/socket.io idea above.

Multiple Socket.io app processes cause each client socket connects and disconnects repeatedly

I am working on a nodejs app with Socket.io and I did a test in a single process using PM 2 and it was no errors. Then I move to our production environment(We use Google Cloud Compute Instance).
I run 3 app processes and a iOS client connects to the server.
By the way the iOS client doesn't keep the socket connection. It doesn't send disconnect to the server. But it's disconnected and reconnect to the server. It happens continuously.
I am not sure why the server disconnects the client.
If you have any hint or answer for this, I would appreciate you.
That's probably because requests end up on a different machine rather than the one they originated from.
Straight from Socket.io Docs: Using Multiple Nodes:
If you plan to distribute the load of connections among different processes or machines, you have to make sure that requests associated with a particular session id connect to the process that originated them.
What you need to do:
Enable session affinity, a.k.a sticky sessions.
If you want to work with rooms/namespaces you also need to use a centralised memory store to keep track of namespace information, such as the Redis/Redis Adapter.
But I'd advise you to read the documentation piece I posted, things might have changed a bit since the last time I've implemented something like this.
By default, the socket.io client "tests" out the connection to its server with a couple http requests. If you have multiple server requests and those initial http requests don't go to the exact same server each time, then the socket.io connect will never get established properly and will not switch over to webSocket and it will keep attempting to use http polling.
There are two ways to fix this.
You can configure your clients to just assume the webSocket protocol will work. This will initiate the connection with one and only one http connection which will then be immediately upgraded to the webSocket protocol (with socket.io running on top of that). In socket.io, this is a transport option specified with the initial connection.
You can configure your server infrastructure to be sticky so that a request from a given client always goes back to the exact same server. There are lots of ways to do this depending upon your server architecture and how the load balancing is done between your servers.
If your servers are keeping any client state local to the server (and not in a shared database that all servers access), then you will need even a dropped connection and reconnect to go back to the same server and you will need sticky connections as your only solution. You can read more about sticky sessions on the socket.io website here.
Thanks for your replies.
I finally figured out the issue. The issue was caused by TTL of backend service in Google Cloud Load Balancer. The default TTL was 30 seconds and it made each socket connection tried to disconnect and reconnect.
So I updated the value to 3600s and then I could keep the connection.

Persist websocket connection object across the multiple server

I am using a websocket library on server for establishing socket connection.
https://github.com/websockets/ws
I have a more than one server in cluster, I want to know how can I use same socket connection object on another server in cluster.
And also I want to know what is the best option for webchat implementation native websocket or socket.io
You cannot use the same actual socket object across multiple servers. The socket object represents a socket connection between a client and one physical server process. It is possible to build a virtual socket object that would know what server its connection is on, send that server a message to then send out over the actual socket from that other server.
The socket.io/redis adapter is one such virtual ways of doing this. You set up a node.js cluster and you use the redis adapter with socket.io. It uses a central redis-based store to keep track of which serve process each physical connection is one. Then, when you want to send a message to a particular client from any of the server processes, you send that message through socket.io and it looks up for you in the redis database where that socket is connected, contacts that actual server and asks it to send the message to that particular client over the socket.io connection that is currently present on that other server process. Similarly, you can broadcast to groups of sockets and it will do all the work under the covers of making sure the message gets to the clients no matter which actual server they are connected to.
You could surely build something similar yourself for plain webSocket connections and others have built pieces of it. I'm not familiar enough with what exists out there in the wild to offer any recommendations for a plain webSocket. There plenty of articles on scaling webSocket servers horizontally which you can find with Google and read to get started if you want to do it with a plain webSocket.

Bypassing socket connections in node.js

I'm working in a project where we need to connect clients to devices behind LAN networks.
Brief description: there are "devices" connected, in a home for example, under a LAN created by a router. These devices create a full webserver, operating under linux, and using nodejs as the backend implementation language. They also have access to Internet, through the public IP of the router. On the other side, there are clients which can choose to which device to connect to.
The goal is to connect the clients with the webServer created by any device.
Up to now, my idea is to try to implement something similar to how TeamViewer works. As I understand, Teamviewer has a central server, which the agents connect to. When an agent connects to the central server, this one gets hold of the TCP connection, keeping it alive. When another client wants to access to the first client, the server bypasses both TCP connections. That way the server acts like a proxy, where it additionally routes the TCP connections. This also allows to connect to clients under LAN or firewalls (because the connections are created always from the clients).
If this is correct, what I would like to implement is a central server, in nodejs as well, which manages a pool of socket connections coming from the different active devices, and when a client wants to connect to one specific device, the server bypasses the incoming TCP connection of the client with the already existing connection of the device.
What I first would like to know is if this is possible in nodejs. My idea is to keep the device connections alive, so clients can inmediately connect to them, creating some sort of pool of device connections.
If implemented in C, I guess I could get hold of the socket descriptor, keeping it alive, and bypassing it to the incoming client request. But in nodejs I can't seem to find any modules that manage TCP connections.
Are there any high level npm packages which do this function? Else, is it possible to use lower level modules (like net) which have those functionalities.
Ideally I would like to implement it with high level modules (express), but if it's not possible, I could always rewrite the server using low level modules.
Thanks in advance

Why do many websocket libraries implement their own application-level heartbeats?

For example socket.io has pingInterval and pingTimeout settings, nes for hapi has similar heartbeat interval settings. This is ostensibly to prevent any intermediates such as over-zealous proxies from closing what seems to be an inactive connection.
But ping/pong frames are part of the websocket protocol and seem to serve the same purpose. So why do websocket library implementors add another layer of ping/pong at the application level?
If I was pushed to guess it would be in case the websocket server is dealing with a client that doesn't respond/support the websocket protocol level ping-pongs.
I did some reading up and made some tests and I think it comes down to this:
Websocket pings are initiated by the server only
The browser Websocket API has isn't able to send ping frames and the incoming pings from the server are not exposed in any way
These pings are all about keepalive, not presence
Therefore if the server goes away without a proper TCP teardown (network lost/crash etc), the client doesn't know if the connection is still open
Adding a heartbeat at application level is a way for the client to establish the servers presence, or lack thereof. These must be sent as normal data messages because that's all the Websocket API (browser) is capable of.

Resources