Socket.io connection to server - node.js

I cant seem to get the socket to connect to the server, im not getting any errors but the socket does not seem to be making a connection with the server
var request=require("request");
var server;
request({url: 'http://localhost:3000/api/designrooms'}, function (err,response, body) {
var designroomID = JSON.parse(body)[0]._id;
console.log(designroomID);
server = request({url: 'http://localhost:3000/api/designrooms' + designroomID})
});
var io = require("socket.io").listen(server);
io.on('connection',function(socket){
console.log("connected");
});

Try paste this into developer console (press enter) and see debug result.
localStorage.debug = '*';

javascript and node are asynchronous.
In your case, this line
var io = require("socket.io").listen(server);
is executed before this line :
`server = request({url: 'http://localhost:3000/api/designrooms' + designroomID})`
due to your request callback. So, your server isn't initialized.
Try to move your listener inside the request callback.

Related

Failed to load resource: the server responded with a status of 426 (Upgrade Required)

I tried to go with the tutorial of this link http://web-engineering.info/node/57
But when I execute node server.js and open the browser http://localhost:3434 it says upgrade required. The server.js file is:
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({port: 3434});
wss.broadcast = function (data) {
var i = 0, n = this.clients ? this.clients.length : 0, client = null;
for (; i < n; i++) {
client = this.clients[i];
if (client.readyState === client.OPEN) {
client.send(data);
}
else console.error('Error: the client state is ' + client.readyState);
}
};
wss.on('connection', function (ws) {
ws.on('message', function (message) {
wss.broadcast(message);
});
});
you have to open your index.html in browser not http://127.0.0.1:3434
its a websocket server. You are trying to make a http connection to a websocket server.
Most probably your server socket at localhost:3434 don't have support for websocket, so the connection is terminated by the client browser.
This error indicates that on localhost:3434 you are running a HTTP server which is incapable to "upgrade" to websocket.
(Since both simple http and websocket begins with a simple http request. In that http request the client ask the server to switch to websocket protocol.)
Should you add this ?
var ws = require('websocket.io')
, server = new ws.Server()
// … somewhere in your http server code
server.on('upgrade', function (req, socket, head) {
server.handleUpgrade(req, socket, head);
});
ref https://www.npmjs.com/package/websocket.io#passing-in-requests
Check this SO too What is an http upgrade?
I tried intercepting the http request
var ws = require('websocket.io')
, http = require('http').createServer().listen(3000)
, server = ws.attach(http)
server.on('connection', function (socket) {
socket.on('message', function () { });
socket.on('close', function () { });
});
https://www.npmjs.com/package/websocket.io#passing-in-requests
For me using the npmjs documentation, I went copy-paste rogue.
Then, debugging my client-side request I noted that the URL parameter I was using was not a string as expected.
But it was shark_s's answer that helped remind me to go look at the console and interpret the error again- so thanks.

connect cmd line socket server via nodejs socket.io

I have a node.js server communicating to a client web page, sending it message. This is working great based on the many tutorials and searching stack overflow :)
Where I am having an issue is when I attempt to startup a separate socket connection to a 3rd party cmd line executable instance runs as a socket server. The 3rd party executable does not adhere to the socket.io namespace/room type of events, so I read that socket.io-events may help where instead of:
socket.on('some key', function(){/**do stuff*/}); I could:
eventRouter.on('*', function(){/*do stuff*/});
For this communication, I am assuming I need to use socket.io-client on the node.js side in order to talk to the cmd executable, but I am getting exceptions trying to do a socket2.use(router); where socket2 is my socket.io-client and router is the socket.io-events object.
All runs on localhost, node to web page is port 8001 and node.js to executable is on port 8002. Please pardon the code, for I have been trying to get this to work for a few days and is a bit ugly now.
The cmd executable to execute and its arguments I have coming from the web page which works. I am able to start the exe. The EXE expects a ACK on each message sent, thus why you see the code emitting it back.
I have a interval where I set and update an element on the web page. I have another element that I set messages (msg).
var http = require('http');
var url = require('url');
var fs = require('fs');
var server;
server = http.createServer(function(req, res){
// your normal server code
var path = url.parse(req.url).pathname;
switch (path){
case '/':
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<h1>Hello! Try the Test page </h1>');
res.end();
break;
case '/socket.html':
fs.readFile(__dirname + path, function(err, data){
if (err){
return send404(res);
}
res.writeHead(200, {'Content-Type': path == 'json.js' ? 'text/javascript' : 'text/html'});
res.write(data, 'utf8');
res.end();
});
break;
default: send404(res);
}
}),
send404 = function(res){
res.writeHead(404);
res.write('404');
res.end();
};
server.listen(8001);
var str = "ack0";
var bytes = [];
for (var i = 0; i < str.length; ++i) {
bytes.push(str.charCodeAt(i));
}
// use socket.io
var io = require('socket.io').listen(server);
// define interactions with client
io.sockets.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('date', {'date': new Date()});
}, 1000);
//recieve client data
socket.on('client_data', function(data){
var spawn = require('child_process').spawn;
console.log('pre-spawned');
spawn(data.cmd, data.args, {});
setTimeout(function() {
console.log('hello world!');
}, 1000);
var aptIO = require('socket.io-client');
var router = require('socket.io-events')();
var socket2 = aptIO.connect('localhost:8002', {reconnect: true});
router.on('connection', function(s){
//send data to client
console.log('apt');
router.on('*', function(sock, args, next){
var name = args.shift(), msg = args.shift();
console.log(name + " " + JSON.stringify(msg));
sock.emit(bytes);
io.sockets.emit('msg', {'msg': JSON.stringify(msg)})
next();
});
s.emit(bytes);
});
console.log('spawned');
// getting runtime exceptions here...have tried various things...
socket2.use(router);
});
});
With the help from JGreenwell, I was able to resolve me issue.
I ended up having the node server communicate to the client html page via socket.io connection for messages. The node server would launch the cmd line executable providing it the port to connect to which is different from the socket.io port used.
Once started, the executable would communicate with the server via the net module. The server would just pass the information on to the socket.io connection. the js in the html page knows how to parse the message in order to increment the progress bar and list the messages in a text area control.
I took it even further by having the messages be broadcast-ed to multiple clients on the socket.io connection.

callback on net.createServer() is called twice

I'm following the tutorial on this tutorial. Here's the code:
var net = require('net')
var chatServer = net.createServer()
chatServer.on('connection', function(client) {
client.write('Hi!\n');
client.write('Bye!\n');
console.log("got msg from http"); //added
client.end()
})
chatServer.listen(9000)
I placed a console.log between the bye and the client.end()
When I run it and hit port 9000, the console.log is outputed twice instead of once.
got msg from http
got msg from http
anyone know why?
Thanks
I'm guessing you're using a browser to test your server. What you're seeing is two different incoming HTTP requests. Try the following code and you will likely see that there are two incoming HTTP requests:
var net = require('net')
var chatServer = net.createServer()
chatServer.on('connection', function(client) {
client.write('Hi!\n');
client.write('Bye!\n');
console.log("got msg from http"); //added
client.on('data', function (data) {
console.log('data: \n%s', data)
});
client.end()
})
chatServer.listen(9000)
The two requests should be GET / and GET /favicon.ico, favicon.ico is the icon which is displayed on the browser tab and bookmarks etc.

var socket = io.connect('http://yourhostname/');?

I try socket.io again since v.1.0 released.
As the doc,
https://github.com/Automattic/socket.io
Server side:
var server = require('http').Server();
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('event', function(data){});
socket.on('disconnect', function(){});
});
server.listen(5000);
Client side
var socket = io.connect('http://yourhostname.com/');
In development, surely
var socket = io.connect('http://localhost:5000/');
It works, but I'm very uncomfortable with hardcoding the hostname(subdomain.domain) in the client code(/index.js).
The index.js is hosted by the http-sever and the socket.io is bundled to the http-server in this configuration.
Is there any smart way not to hardcode the hostname but to code in some relative path?
Thanks.
EDIT:
When I try:
var socket = io.connect('./');
The connection error:
GET http://.:5000/socket.io/?EIO=2&transport=polling&t=1401659441615-0 net::ERR_NAME_NOT_RESOLVED
is like this, so at least the port number (5000) is obtained properly without hardcoding in the client side.
Final answer.
I have totally forgotton that we can obtain the current url/domain in browser.
window.location.hostname
So, simply goes:
'use strict';
/*global window, require, console, __dirname, $,alert*/
var log = function(msg)
{
console.log(msg);
};
log('init');
$('document').ready(function()
{
var io = require('socket.io-client');
var socket = io.connect(window.location.hostname);
socket.on('connect', function()
{
log('socket connected');
});
});
You have to remember that Node.js is not a web server. It's a platform. When you specify a relative path, it doesn't know that you mean "relative to the current domain."
What you need to do is send the domain to the client when you send them the webpage (I don't know the specifics of your setup, but perhaps using a template variable?), and send them the localhost:5000 domain if you're in development, or your real domain if you're in production (alternatively, you can use a library like nconf, but you get the idea).
dunno, so far I did as follows:
'use strict';
/*global window, require, console, __dirname, $,alert*/
var log = function(msg)
{
console.log(msg);
};
log('init');
$.getJSON("../config.json", function(data)
{
var host = data.url;
var port = data.port;
$('document').ready(function()
{
alert(host + ':' + port);
var io = require('socket.io-client');
var socket = io.connect(host);
socket.on('connect', function()
{
log('socket connected');
});
});
});
It's browserified with socket.io-client.

where to add socket.io in my node.js app

So i have this basic node.js server running, now i want to add another layer to it with socket io. I can use socket io, the example here is pretty simple and works great. But my app is much bigger so I do this thing where i load a bunch of resources and then load this server module by calling start_app.
I know i cant put io.listen(app) on line 3 because my server hasn't started yet.
I need that functional dependency, so how do i add add socket.io to the mix?
var app= require('http') // all http requests go to onRequest
, url= require('url') // path info stuff
, io = require('socket.io') // socket io
function start_app(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname.replace("/","")
route(handle, pathname, request, response)
}
app.createServer(onRequest).listen(process.env.PORT || 8888)
io.listen(app)
console.log(". http://localhost:8888 .")
}
exports.start_app = start_app;
my error:
...socket.io/lib/manager.js:104
server.on('error', function(err) {
^
TypeError: Object #<Object> has no method 'on'...
Instead of your code:
app.createServer(onRequest).listen(process.env.PORT || 8888)
io.listen(app)
Could you do it like below?
var createdServer = app.createServer(onRequest).listen(process.env.PORT || 8888);
io.listen(server).on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg);
socket.broadcast.emit('message', msg);
});
});
We need the actual created server so socket.io can listen to that. Then handle the 'connection' event.
changeing the first few lines of the server fixed it.
I'm not 100% sure why this works but, I guess it makes sense that the server shouldn't start until this function is called, since its the entry into the main event loop of the app.
var app // all http requests go to onRequest
, url = require('url') // path info stuff
, sio = require('socket.io') // socket io
function start_app(route, handle) {
app = require('http').createServer(onRequest)
sio = require('socket.io').listen(app)
app.listen(process.env.PORT || 8888)

Resources