Node + Connect + WebSockets - node.js

I am looking for a WebSockets lib/middleware for connect
The one I found so far is Socket.IO-connect however it uses patched version of Connect.
This is an issue mainly due to the separation of patched version of Connect from the main branch.
Can you recommend a good library?

Right now, it's a bad time for WebSockets, Mozilla and Opera won't ship them with the upcoming versions due to some problems with the protocol and broken proxies, which allow for cache poisoning. It very likely that Google will also drop support until the protocol has been fixed.
So as of now, it doesn't make much sense to search for a middleware as the protocol will change very soon and then you'll have to search yet again, so for now you can just as well use the patched version if you really need to.
For details see:
http://hacks.mozilla.org/2010/12/websockets-disabled-in-firefox-4/
http://blog.pusherapp.com/2010/12/9/it-s-not-websockets-it-s-your-broken-proxy

You do not need a connect middleware for socket.io, and infact it's probably not the best way to go about using socket.io with connect. Here is what I do:
var connect = require('connect');
var io = require('socket.io');
var server = connect.createServer(
connect.router(function(app) {
app.get('/', function(req, res, next) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/assets/index.html', 'utf8'));
// above file contains <script src="/socket.io/socket.io.js" type="text/javascript"></script>
});
})
).listen(80);
var socket = io.listen(server);
socket.on('connection', function(client) {
client.on('message', function(message) {console.log(message)});
client.on('disconnect', function() {});
});

My version of socket.io-connect should work well.

Related

How to handle live messaging in Mean stack application?

I'm planning to develop a MEAN Stack application. After searching internet i'm not getting myself so clear on how to handle live messaging in my application which would just work like whatsapp/fb messenger or any other chat applications.
Initially i thought of using setTimeout function and make a REST call for latest data on some specified no.of seconds, but i don't know whether it's a feasible option.
Can anyone help me to understand what would be the best practice to update messages on both server and client sides?
You can use Socket.io. It is a websocket which allows you to communicate between browser and server. It's very easy to setup and start using.
You can install it with npm install --save socket.io (assuming you installed express already 'cause you want a MEAN app)
Then you can start with basics like this:
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
You can find the documentations in here
Hope it helps!

Socket.io + Azure web sockets issue

I am working on a multiplayer chess game with NodeJS and socket.IO.
I have problem hosting it on Azure tho.. I tried many different approaches, a few mentioned:
Forcing the application to only use WebSockets by adding the code below:
io.configure(function() {
io.set('transports', ['websocket']);
});
Added <webSocket enabled="false"/> in web.config file..
Note: This disables the IIS WebSockets module, which includes its own implementation of WebSockets and conflicts with Node.js specific WebSocket modules such as Socket.IO. If this line is not present, or is set to true, this may be the reason that the WebSocket transport is not working for your application.
Matching origin protocol to ensure no SSL issues.
io.configure(function() {
io.set('match origin protocol', true);
});
I now started from scratch, since I thought my server-side part was corrupt, and tried Socket.io chat example instead.
I followed the steps.
Created a new web app on Azure.
Published my files through FileZilla FTP.
Enabled Web Sockets on Azure for my app (disabled by default).
STILL THE SAME ERROR! See picture below.
Anyone? I am unsure if it's a client-side or server-side issue. It seems like it's trying to XHR-poll instead of using web sockets..
Thanks in advance.
I got it working, thank you Chris Anderson-MSFT for your help.
The weird thing that occurred for me when deploying with FTP was that my node_modules folder differed with version(s) specified in my package.json.
I solved this by connecting my web app on Azure to a local Git repository and deploying the app through git. This connects my packages recursively and matches correct versions.
I also needed to enforce my client-side socket-io to use web sockets by specifying transport method:
var socket = io({transports:['websocket']});
And this is what my server-side file ended up looking like:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
app.use(express.static('public'));
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/default.html');
});
io.on('connection', function(socket) {
io.set('transports', ['websocket']);
console.log('new connection on socket.io');
socket.on('move', function(msg) {
socket.broadcast.emit('move', msg);
});
});
server.listen(port, function () {
console.log('Server listening at port %d', port);
});

socket.io example sometimes not connecting client side when using a reverse proxy

Using node-http-proxy, I've set up a reverse proxy for routing requests:
var httpProxy = require('http-proxy');
var server = httpProxy.createServer({
hostnameOnly: true,
router: {
'www.example.com': 'localhost:3002'
}
}).listen(80);
Now, when I run the first example on http://socket.io/#how-to-use, the socket is sometimes not connecting with the client. I created two files to test this: server.js and index.html. To start the node application, i run server.js.
server.js:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(3002);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
console.log("Socket connected");
});
index.html:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
setInterval(function() {
console.log(socket.socket.connected);
}, 1000)
</script>
When the client does not connect, after the socket connects with the server, I repeatedly get the following output with intervals of +/- 10 seconds:
debug - setting request GET /socket.io/1/xhr-polling/Cqcw5xUjQ-B-Hw3FGF7Y?t=1385128607702
debug - setting poll timeout
debug - discarding transport
debug - cleared heartbeat interval for client Cqcw5xUjQ-B-Hw3FGF7Y
Now, when I refresh the browser a few times, the socket always connects with the server (that is, it always logs "Socket connected"), but sometimes it does not connect client side: console.log(socket.socket.connected) sometimes repeatedly prints "false" after refreshing index.html, and after another page refresh, it may repeatedly print "true" or "false" again if the socket did not or did connect with the client.
The example does work client-side when I do not use the reverse proxy, so when I run server.js on port 80 on www.example.com. It would be great if someone could point me out what could be the cause of this problem. I am using node.js v0.8.23, socket.io version 0.9.14 and node-http-proxy version 0.10.1.
UPDATE
Probably, I am actually using node v0.10.21. I thought I was using v0.8.23 by switching the node version using nvm, but for some reason it keeps switching back to v0.10. It is a known issue that http-proxy does not support web sockets for node versions later than 0.8, so that may be the cause. I am using robertklep's solution until I find something better.
I think the issue might be that socket.io is initially trying to use WebSockets as a transport medium and when that doesn't work (I don't know if node-http-proxy can proxy WS connections), it falls back to a transport that does work (xhr-polling) but the client and/or server gets confused in the process.
Try disabling the websocket and flashsocket transports to see if that makes it more reliable:
io.set('transports', [ 'xhr-polling', 'jsonp-polling', 'htmlfile' ]);
(more info)
It really was the node version I was using. Node-http-proxy does not work for node version >0.8 (see Node http proxy with proxytable and websockets). I thought I was using v0.8.23 but I was actually using v0.10.21. By using n, I could get node working for v0.8.23 for sure, and now it seems to work. I highly recommend n for resetting the node version.

How to send a temporary chunk of html and js to a running app on node.js

I just got my first app up and running on Node.js. As of now, it is simply serving up a static file. But I have a few ideas that will be implemented down the road so I'm going ahead and getting Node setup so I'll be ready for it when that time comes.
// get modules
var express = require('express');
var fs = require('fs');
// create app instance
var app = express();
// static files middleware
app.use("/assets", express.static(__dirname + '/assets'));
// main route
app.get('/', function(req, res) {
var html = fs.readFileSync('assets/views/main.html', 'utf8');
res.send(html);
});
// make web server listen on specific port
app.listen(8080);
NOTE: I realize I don't need Express to serve one route, but I figured what's the harm in getting a head start on that as well?! :)
The first idea i had is to make a way to let all users currently using the app that there has been an update and that they must refresh their browser. There is no need to save the current state of the app as it is pretty basic.
So, if I am a user, I'm using the app and boom, I get a pretty little modal-window-alert-notification thingy letting me know that I need to refresh.
Also, if some user loads the app AFTER I have sent the alert, that user should not see the alert at all (because they should already be seeing the new changes).
I have done some googling on the subject and I'm just not satisfied with the examples i found. I do not think I want to have to update a notifications.xml file (which node.js would be watching) to push a new notification.
One solution I can think of would be to make a command that can be executed from the command line that will (somehow) send a new notification to the app. Perhaps using something like Grunt.js (I'm not sure if it would be a good fit for this as I've never used it). Basically, once the notification has been sent, all traces of it should disappear. That's why I think a command line approach would be good.
Here's my question: How (generally speaking) should I implement something like this? I am a Node.js newbie but I am pretty comfortable with javascript and the command line.
Please feel free to offer up any alternative solution you think would be better for me (other than a command line approach), or any tools that you think could help me.
Thanks!
If you want to push updates to a web client, one way is to use something like Socket.io. This creates a two-way pipe between client and server that you can use to asynchronously push updates through.
Sample server:
var app = require('express').createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
Sample client:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
alert('New news has come in! Please refresh your page!');
socket.emit('my other event', { my: 'data' });
});
</script>
The other option is to poll from the client using Javascript to actively look for updates. You would need to keep some state on the server for each client that would determine if that client required an update. The client would then make a get request on some timer interval (once a second, for example) to a secondary route and the server would reply with 'Yes, you need an update' or 'No, you don't need an update'. If yes, the client Javascript would then pop up your modal box and tell the user to refresh.

Socket.io 0.7.9 connection issues

I am attempting to upgrade to socket.io 0.7.9 and have run in to problems.
I have used the basic example from the socket.io homepage. My server is:
var http = require('http'),
url = require('url'),
https = require('https'),
fs = require('fs'),
crypto = require('crypto'),
io = require('../'),
sys = require(process.binding('natives').util ? 'util' : 'sys'),
server = http.createServer(function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();
});
server.listen(80,"[MYIP]");
var io = io.listen(server), buffer=[];
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
It connects OK on some computers but not on others. It is the same across all browsers.
Does anyone know why this would happen? Could there be some local networking issue that causes this?
UPDATE
It appears that the people who are unable to connect from their computers are running anti virus with real time web shields that seem to block the connection. When they turn it off, it connects OK on some browsers...
I have been using socket.io and node.js for the last two months and some issues like yours happened to me too.
Firewalls are often a problem with the port 80, especially when used with a DNS (like in a corporate network) because they will temper with the headers of the socket packages. One work around could be to try another port.
My application has an apache server on the port 80 and my websocket is on the port 843, everything is working fine on Firefox and Chrome.
You can use the xhr-polling fallback option to bypass this type of errors by adding this script:
io.set('transports', ['websocket','xhr-polling']);
xhr-polling offers less real-time performance, but is really dependable and works on most browsers and network configurations.
I hope this will help you!

Resources