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!
Related
I have a server set up using node.js and I'm trying to connect to the server with socket.io. The server used to work perfectly 2 months ago but for some reason it does not work anymore. The server code looks like the following:
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
var io = require('socket.io')(server);
io.sockets.on('connection', function (socket) {
console.log ('Client connected.'); });
console.log ('Server started.');
server.listen(3000, '0.0.0.0');
On my client side, I'm using the line
socket = io.connect("http://localhost:3000");
to try to connect to my server, but it doesn't work. The connection works perfectly if I use the line
socket = io.connect("http://127.0.0.1:3000");
If I type localhost:3000 on the browser, it sends me to the page saying Hello World as intended, same as 127.0.0.1, so it is not working only when I'm using io.connect.
Things that I have tried are:
changing the host file (adding the line 127.0.0.1 localhost, removing the line including ::1, making a new host file and overwriting it)
trying it on a different machine, still the same problem
resetting the router settings.
pinging localhost on a cmd prompt, it says reply from ::1: time<1ms
installing different version of socket.io and node.js (both the most recent ones and versions 2 months ago)
Considering what happens from web browser, localhost seems to work but it only does not work when I use socket.io with it. I have been unable to solve this problem that suddenly appeared, so I would appreciate it a lot if someone can give me some insights on what can be causing this.
It seems like an IPv4/IPv6 issue. You may try changing this:
server.listen(3000, '0.0.0.0');
to this:
server.listen(3000, '::1');
or this:
server.listen(3000);
I have an Android app that uses websockets via a NodeJS server hosted with Azure. For the passed six months, everything has been fine. Today, all is not fine. When I try to connect to my server, I get the response "No address associated with hostname."
I have websockets enabled in my config tab in the management console, also in the web.config file so that Node handles the websocket and not iis. I have changed nothing, toggled the websocket settings, nothing works. I have restarted the server many times. I also created a new website and migrated everything, still the same issue. I cannot get tech support from Microsoft because the website is a free one. I am aware that there is a max of 5 connections to the websocket; this is not the issue.
My server is using the 'ws' websocket module. I have taken my server.js code down to the minimum for testing. This is it now...
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ port: process.env.PORT || 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {});
ws.on('close', function closing(code, message) {});
if (ws.readyState == 1)
ws.send('message from the server!');
});
It still does not work. I replaced the entire file with the code below and the server responds with text in the browser. Of course, this is not websocket, but it shows that the server is able to respond to http requests.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end('Hello, world!');
}).listen(process.env.PORT || 8080);
Has anything changed with the usage of websockets? Have recent restrictions been placed I am unaware of?
I made a basic chat app using node.js, express and socket.io. It's not too different from the tutorial chat app for socket.io, it simply emits events between connected clients. When I ran it on port 3001 on my server, it worked fine.
Then I made a proxy server app using node-http-proxy which listens on port 80 and redirects traffic based on the requested url to various independent node apps I have running on different ports. Pretty straightforward. But something is breaking. Whenever anyone disconnects, every single socket dis- and re-connects. This is bad for my chat app, which has connection-based events. The client consoles all show:
WebSocket connection to 'ws://[some socket info]' failed: Connection closed before receiving a handshake response
Here's what I think are the important parts of my code.
proxy-server.js
var http = require('http');
var httpProxy = require('http-proxy');
//create proxy template object with websockets enabled
var proxy = httpProxy.createProxyServer({ws: true});
//check the header on request and return the appropriate port to proxy to
function sites (req) {
//webapps get their own dedicated port
if (req == 'mychatwebsite.com') {return 'http://localhost:3001';}
else if (req == 'someothersite.com') {return 'http://localhost:3002';}
//static sites are handled by a vhost server on port 3000
else {return 'http://localhost:3000';}
}
//create node server on port 80 and proxy to ports accordingly
http.createServer(function (req, res) {
proxy.web(req, res, { target: sites(req.headers.host) });
}).listen(80);
chat-app.js
/*
...other modules
*/
var express = require("express");
var app = exports.app = express(); //I probably don't need "exports.app" anymore
var http = require("http").Server(app);
var io = require("socket.io")(http);
io.on("connection", function (socket) {
/*
...fun socket.on and io.emit stuff
*/
socket.on("disconnect", function () {
//say bye
});
});
http.listen(3001, function () {
console.log("listening on port 3001");
});
Now from what I've read on socket.io's site, I might need to use something to carry the socket traffic through my proxy server. I thought that node-http-proxy did that for me with the {ws: true} option as it states in their docs, but apparently it doesn't work like I thought it would. socket.io mentions three different things:
sticky session based on node's built in cluster module
socket.io-redis, which allows separate socket.io instances to talk to each other
socket.io-emitter, which allows socket.io to talk to non-socket.io processes
I have exactly no idea what any of this means or does. I am accidentally coding way above my skill level here, and I have no idea which of these tools will solve my problem (if any) or even what the cause of my problem really is.
Obligatory apology: I'm new to node.js, so please forgive me.
Also obligatory: I know other apps like nginx can solve a lot of my issues, but my goal is to learn and understand how to use this set of tools before I go picking up new ones. And, the less apps I use, the better.
I think your intuition about needing to "carry the socket traffic through" the proxy server is right on. To establish a websocket, the client makes an HTTP request with a special Upgrade header, signalling the server to switch protocols (RFC 6455). In node, http.Server instances emit an upgrade event when this happens and if the event is not handled, the connection is immediately closed.
You need to listen for the upgrade event on your http server and handle it:
var proxy = httpProxy.createProxyServer({ws: true})
var http = http.createServer(/* snip */).listen(80)
// handle upgrade events by proxying websockets
// something like this
http.on('upgrade', function (req, socket, head) {
proxy.ws(req, socket, head, {target:sites(req.headers.host)})
})
See the node docs on the upgrade event and the node-http-proxy docs for more.
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.
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.