4

Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.

I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.

Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.

var myemail = "email@gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');

socket.on('connect', function(){
    try {
        console.log('socket connect');
        socket.emit('configure', {email:myemail, deviceid:device_id});
    } catch(e) {
        console.log(e);
    }
});
socket.emit("/" + device_id, "45678");

...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.

var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables

var myemail = "email@gmail.com";
var device_id = '12345'; 

var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');

//Connect listener
socket.on('connect', function(){
   try {
      console.log('socket connect');
      socket.emit('configure', {email:myemail, deviceid:device_id});
   } catch(e) {
     console.log(e);
   }
});
socket.emit("/" + device_id, "45678");

Any ideas?

UPDATE

Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).

debugging output image link

Lee
  • 81
  • 1
  • 5
  • Here's a guess. What happens if you want until inside the `connect` event in order to do your `socket.emit("/" + device_id, "45678");`. You are attempting that `.emit()` before the connect has finished. Perhaps this is somehow not causing a problem in the browser, but is on node.js? Timing could be different on the two platforms, perhaps. – jfriend00 Aug 20 '17 at 03:09
  • Oh, and btw, socket.io-client works just fine in node.js to connect to other socket.io servers so that is not an issue. – jfriend00 Aug 20 '17 at 03:10
  • FYI, socket.io has various debug modes that will give you very verbose logging on what's going on too. That might elucidate what is happening. – jfriend00 Aug 20 '17 at 03:14
  • Thanks jfriend00 for the response. Tried adding the emit into the on.("connect") function, didn't work - anyway, it's the initial handshake emit already inside the on connect function that isnt working. ... Also tried using the IP of the server instead of the name. Regarding the debug modes, any thoughts on what i should be looking for? I can see it is not connected but not sure what to look for. – Lee Aug 20 '17 at 04:09
  • Are you sure you have the right version of socket.io-client on your server to match what you're trying to connect to? socket.io can be picky about matching client and server versions. I don't know the debug info in socket.io to know what to look for. If you want to post all the debug output somewhere, I'll look at it. – jfriend00 Aug 20 '17 at 04:20
  • both your clients work perfectly with my local server... can you try http instead of https? just thinking.. – mk12ok Aug 20 '17 at 14:55
  • Thanks all. I verified that I'm using 2.0.3 of socket.io and socket.io-client; and cannot use http - presumably that's there for the security of the server I'm trying to connect to. When I try to use http (even in the flatfile client-side javascript running in chrome), I see the following error in the console: polling-xhr.js:264 GET http://example.net:3000/socket.io/?EIO=3&transport=polling&t=Lu2o_eg net::ERR_EMPTY_RESPONSE – Lee Aug 21 '17 at 03:19
  • @jfriend00 I just updated post with debug infoif you wouldnt mind taking a look – Lee Aug 21 '17 at 03:56
  • ALL websocket connections are initiated with an http request. And, by default, all socket.io connections start with http polling and then attempt to upgrade to a webSocket (both of which need http to proceed). So, I'm pretty confused when you say "cannot use http". What does that mean? That sounds like a problem to me. – jfriend00 Aug 21 '17 at 04:18
  • The logs you added are telling us that the client is attempting to establish an http polling connection to the server (as the usual first step in establishing a socket.io connection) and that is failing. – jfriend00 Aug 21 '17 at 04:19
  • What does your other comment about credentials have to do with this at all? – jfriend00 Aug 21 '17 at 04:20

2 Answers2

4

Solved this - issue was that the server I was connecting to required use of https, so I needed to add

{secure: true,    rejectUnauthorized: false}

after the url to connect to.

Full working example:

const myemail   = email@email.com;
const device_id   = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true,    rejectUnauthorized: false});

function doStuff(){


//Listener
socket.on('connect', function(){
   try {
      console.log('socket connect');
      socket.emit('configure', {email:myemail, deviceid:device_id});

   } catch(e) {
     console.log(e);
   }
});

socket.emit("/" + device_id, "003021");


}


doStuff();
Lee
  • 81
  • 1
  • 5
1

I think the line causing the issue is :

var socket = io.connect('https://example.net:3000');

I managed to make a working example using this code :

const myemail = "email@gmail.com";
const device_id = '12345'; 
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
 try{
   console.log('socket connect');
   socket.emit('configure', {email:myemail, deviceid:device_id});
 }catch(e){ console.log(e); }
});
EMX
  • 6,066
  • 1
  • 25
  • 32
  • That's not making any difference for me - and I see that a few people have managed to make this work in their own localhosts. My hunch is it has something to do with the login credentials (email and device id) passed to the socket on connect - for some reason those arent being accepted when I try to execute server side... – Lee Aug 21 '17 at 03:21
  • Why do you think that? You have to go in parts, does the client handshake with the server? (does your server inform of a client connection?) You say it works from localhost but not from other machine? > Maybe it has something to do with firewall? – EMX Aug 21 '17 at 08:29