net.Socket.remoteAddress is undefined on connect in node js net module - javascript

I'm trying to retrieve the IP address of a new socket on the client side.
like so
var socket = net.Socket()
console.log(socket.remoteAddress)
However, this prints undefined to the console
On the server side, socket.remoteAddress is exposed with no issues at all using this code.
net.createServer(function(socket){
console.log(socket.remoteAddress, socket.remotePort)
}).listen(4000)
So my question is, am I experiencing a bug, or am I misunderstanding how Socket/TCP connections are handled.
I understand that in TCP, typically the client port is chosen at random, but I don't imagine this should make it undefined as I'm experiencing- and at the very least, the public IP should be available to the API so long as I'm connected to a network. Admittedly, I am a bit of a novice with networking, but this seems a bit weird.

Related

Keeping Web Socket Server Alive

Zup coders. I've implemented a simple website that uses Web Sockets PHP (Consik Yii2 solution: https://github.com/consik/yii2-websocket) vs JS (Html5).
Everything is working fine, I only have one issue with my solution, making sure the server is always alive.
I though about saving the WebSocket Instance into Cache and throw a cron that checks the state of the instance. I installed memcached and found out that i can´t save a serialized version of the WebSocket Server instance. ¿Is this a good solution? ¿Would Redis Caché fix this?
I also thought about using client side JS to react to "Error during WebSocket handshake: Unexpected response code: 200" but i can't seem to get it working. I also don't like making the URL that starts websockets public.
Ex:
connect = function(){
websocket = new WebSocket(webSocketURL);
websocket.onerror = function(){
$.get( "/startWebSocketServer",
function(data){
connect();
}
);
};
};
connect();
Thanks!
I think that as matter of fact you need a process supervisor who takes care to "supervise" your server process and do actions in response of process/system events like crash, restart etc..
There are several solutions for each case (standard OS implementations, personal preferences, fit your need), here a list http://without-systemd.org/wiki/index.php/Init , Service managers section could best fit your needs.
Supervisord is easy to setup and configure, it could be a good start thanks to a good bunch of examples around the net.
Solution 1: using a cache could not be the most orthodox way to implement a custom-made supervisor.
Solution 2: is legit as long as it informs user about a problem, the call to an exposed endpoint to start a service IMHO could be a security flaw.

Websocket can't send/receive messages on Chrome/Firefox, works fine on Microsoft Edge

I'm making a remote debugging tool for Unity(C#), and I've set up a C# WebSocket server in the game that emits Log messages.
The remote debugging client is in JavaScript, on a page served by an http server also created by the game.
I seem to be running into issues sending messages on some browsers, and I'm not sure why. I am running the websocket server on localhost and running the client locally, and I know that kind of stuff is not really liked by chrome/firefox. But the weird thing is that I'm not getting any hard errors or exceptions. Failures seem to fail silently.
I'm pretty certain that the issue is JS/Browser related as the C# websocket server works and receives connections in all cases.
Anyway, here's the socket part of the JS code:
var socket = null;
var host = "ws://"+window.location.hostname;
var port = 55000;
var url = host+":"+port+"/msg";
function CheckSocketStatus()
{
if(socket!=null){
console.log(socket.readyState);
}
}
function CreateSocket()
{
socket = new WebSocket(url);
socket.onopen = function()
{
// // Web Socket is connected, send data using send()
console.log("Socket Open!");
socket.send("Here's a client message for ya!");
};
socket.onmessage = function (evt)
{
var message = evt.data;
console.log("MSG: " + message);
var obj = JSON.parse(message);
console.log(obj)
console.log(obj.type)
if(obj.type == "log"){
console.log("Recieved Log");
handleLogMessage(obj);
}
};
socket.onerror = function()
{
console.log("Error!");
}
socket.onclose = function(event)
{
// websocket is closed.
console.log(event.code);
console.log("Connection is closed...");
socket = null;
};
}
In all cases, when I call CreateSocket() a socket gets created and successfully connects to the server. I also have that CheckSocketStatus() function which returns "1" after the socket opens (Which should mean open/ready to send/receive). After that, here are the results:
Chrome:
Chrome will immediately close after connecting. The only thing I do in the onopen() function is a console.log() and a send(). If I remove the send() then the socket will stay open. I do not receive any messages from the server.
Firefox:
Firefox will keep the socket open indefinitely even if I call the send() function in onopen(). However, the server does not receive any messages from the client and vice versa. I feel like I managed to it to send client->server earlier but I could not reproduce that while testing for this question.
Microsoft Edge:
Weirdly enough, Edge works just fine. I can receive and send messages. Works exactly as intended.
Node Webkit (nw.js):
I'm also trying to write this as a nw.js app. Predictably, as it's running on chromium (or something googly), it produces the same results as Chrome.
So I'm not really sure what's going on. I'm not really a web programmer so intricate http stuff is not really my forte. I'm really hoping it's just a Local file issue with chrome/firefox and that it'll work fine on those platforms if I'm connecting to an external host. I'll try to test this tomorrow at work with some non-localhost server, and I'll update with my findings.
I guess the answer I'm looking for is what these symptoms point to and how I can get chrome/firefox/webkit to work properly.
Also what does Edge do here that the others do not?
Thanks in advance! If you need any more info from me please just ask! I didn't want to overload this question just in case there's a simple answer.
Update:
So I just tried connecting from my laptop to my desktop and the same issues still persist. So to my surprise it's not a local issue. I'm a bit stumped. I might have to look at the server code as well. I've also been told to try to use a wrapper, like socket.io, that might solve some platform dependent issues.I've worked with Socket.io/Unity before but I don't think I was having these issues (I wasn't running a server on the C# side that time, there don't seem to be any good socket.io server implementations on C#, and I'm not sure if socket.io interfaces with normal websockets). So that might point to a problem with my implementation on the C# side.
So I figured it out, thanks to gman. I looked at some of his code and noticed that he used a setting in his WebSocketBehavior class called "Ignore Extensions".
The websocket-sharp documentation has this to say:
"If it's set to true, the service will not return the Sec-WebSocket-Extensions header in its handshake response."
"I think this is useful when you get something error in connecting the server and exclude the extensions as a cause of the error."
So I guess that that header did not jive well with Chrome/Firefox. I'm still doing some testing but this solved the behavior I was seeing with those browsers.
So if you get similar errors, do that!

Node JS live text update with CloudMQTT

I have a node server which is connecting to CloudMQTT and receiving messages in app.js. I have my client web app running on the same node server and want to display my messages received in app.js elsewhere in a .ejs file, I'm struggling as to how best to do this.
app.js
// Create a MQTT Client
var mqtt = require('mqtt');
// Create a client connection to CloudMQTT for live data
var client = mqtt.connect('xxxxxxxxxxx', {
username: 'xxxxx',
password: 'xxxxxxx'
});
client.on('connect', function() { // When connected
console.log("Connected to CloudMQTT");
// Subscribe to the temperature
client.subscribe('Motion', function() {
// When a message arrives, do something with it
client.on('message', function(topic, message, packet) {
// ** Need to pass message out **
});
});
});
Basically you need a way for the client (browser code with EJS - HTML, CSS and JS) to receive live updates. There are basically two ways to do this from the client to the node service:
A websocket session instantiated by the client.
A polling approach.
What's the difference?
Under the hood, a websocket is full-duplex communication mechanism. That means that you can open a socket from the client (browser) to the node server and they can talk to each other both ways over a long-lived session. The pro is that updates are often times instantaneous without having to incur the cost of making another HTTP request as in the polling case. The con is that it uses a socket connection that may be long-lived, and there is typically a socket pool on any server that has limited ability to deal with many sockets. There are ways to scale around this issue, but if it's a big concern for you, you may want to go with polling.
Polling is where you set up an endpoint on your server that the client JS code hits every now and then. That endpoint will return you the updated information. The con is that you are now making a new request in order to get updates, which may not be desirable if a lot of updates are expected to come through and the app is expected to be updated in the timeliest manner possible (most of the time polling is sufficient though). The pro is that you do not have a live connection open on the server indefinitely.
Again, there are many more pros and cons, these are just the obvious ones. You decide how to implement it. When the client receives the data from either of these mechanisms, you may update the UI in any suitable manner.
From the server end, you will need a way to persist the information coming from CloudMQTT. There are multiple ways to do this. If you do not care about memory consumption and are ok with potentially throwing away old data if a client does not ask for it for a while, then it may be ok to just store this in memory in a regular javascript object {}. If you do care about persisting the data between server restarts/crashes (probably best), then you can persist to something like Redis, Mongo, any of the SQL stores if your data is relational in nature, or even a regular JSON file on disk (see fs.writeFile).
Hope this helped give you a step in the right direction!

Determine if Request is Local in Node.js app

I am learning Node.js. While creating a web site, I will run the web site locally (on localhost). When it is deployed, it will run on other servers. My question is, how do I determine if a request is from localhost or not in Node? In ASP.NET, I could use Request.IsLocal. I'm trying to figure out how to do that in Node.
Thank you!
There's server.address() to get the server address.
And request has connection and socket objects, as both might hold remote address (in a remoteAddress property) depending on a type of current connection.
But if the server is behind a reverse proxy, you'll have to pull it from appropriate header, most likely x-forwarded-for. However I'm not sure if that holds if proxies are chained.
So, to conclude, you'd do something along the lines of:
function cliAddress(req) {
return req.connection.remoteAddress || req.socket.remoteAddress || req.headers['x-forwarded-for'];
}
server.isLocal = function(request) {
return server.address() === cliAddress(req);
}
And if you use express.js see Express.js Req.IP API.

websocket client discovering server

I am in a situation where I want my websocket client to connect to server but server ip or dns name is unknown. Both client and server are in local network(connected to same router). I tried something like this....
var socket;
for(var i=1; i<255; i++) {
socket = new WebSocket('ws://192.168.1.'+i+':8080/service');
socket.onopen = function () {
console.log('WebSocket Connected!!');
};
socket.onclose = function (event) {
console.log('WebSocket Disconnected!!');
socket.close();
};
socket.onmessage = function (event) {
console.log('WebSocket receive msg: ' + event.data);
}
}
This works but I am not sure if I am doing it right or if there is a better way to do it. Any help is appreciated.
Have you tried hooking up an onerror listener to see what errors are being thrown? It's possible that you're finding the server but that some mis-configuration in the server is causing it to error out before the connection is opened.
WebSockets is still a very actively evolving standard. There are multiple drafts out there and some browsers support some drafts but not others. Old drafts are often considered insecure, so some browsers don't support them, while other browsers only support the old drafts because they haven't been updated for the newer ones. Also, servers may be in the same boat. It's kind of the wild west.
I suggest putting in robust error handling and also fallback when things aren't working right. Packages like Socket.io offer this kind of transparent fallback support. I suggest checking that out if you're looking for a quick solution. However, if you're just using this as a learning experience (and I encourage such behavior!), you will want to hook up an onerror handler to see what's going on and why each connection fails.
This solution would of course scale horribly when you deploy on a network larger than class A. And when there is more than one websocket server on the network, you wouldn't know which one to hit.
But as long as there is no DNS and no static IP addresses on your network, port-scanning the whole IP range is the only way to find the server.
Are you sure it's impossible to assign a static IP address to the server machine? Most consumer grade routers don't strictly enforce the use of DHCP and usually it's not a problem when only some machines are configured with static IP addresses. Some router firmwares also allow to configure the DHCP server to always assign the same IP address to specific MAC addresses.

Categories