my friend and I are both using the same wifi network with open ports for both of us. My friend is listening on port 8000 and I'd like to send him a message.
How can I achieve that using node and socket.io ? Thanks a lot
There are many ways to setup a simple messenger, the standard one is to setup a single socket.io server either on your or your friend's machine, something like this:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(8000);
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.on('connection', function (socket) {
console.log("user connected!")
socket.on('message', function (message) {
//Sends message to all connected sockets
socket.broadcast.emit("message")
});
});
Then your index.html should have some code for connecting to server and sending messages:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://server-ip-or-domain-name:port');
socket.on('message', function (message) {
//processing incoming message here
console.log(message);
});
function sendMessage(msg){
//sends message to server
socket.emit("message", msg);
}
</script>
In this setup both you and your friend should be able to reach the server machine. Use pings for debuging.
p.s. havent tested the code above, but that's the idea.
I'm experimenting this issue at game.html
GET http://localhost/socket.io/socket.io.js 404 (Not Found) game.html:1
Uncaught ReferenceError: io is not defined game.html:3
My game.html file
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost/game.html');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
And my server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(5667);
function handler (req, res) {
fs.readFile(__dirname + '/game.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) {
socket.emit('news', { hello: 'world' });
});
It was working fine when I was using index.html instead of game.html
It looks like you're not retrieving game.html from the Node app, because the socket.io.js file seems to be retrieved from an HTTP port running on port 80 whereas your Node app is running on port 5667.
Also, your client-side connection string is incorrect:
var socket = io.connect('http://localhost/game.html');
That also tries to contact a server on port 80 (and I don't know what game.html is doing there).
So try this:
change the client-side connection string to var socket = io.connect();
start your Node app
open http://localhost:5667/ in your browser
And see if that works better.
I'm trying to do cross-domain socket.io, but I'm experiencing an issue:
I always get XMLHttpRequest cannot load http://handsonwithnodejs.samarthwiz.c9.io/socket.io/1/?t=1358882710333. Origin https://c9.io is not allowed by Access-Control-Allow-Origin.
Server code:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(process.env.PORT);
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.set('origins', '*:*');
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
On line 19 io.set('origins', '*:*');I tried replacing ':' with '*', 'https://c9.io', 'c9.io','https://c9.io/' and '.', some times when I add something like 'c9.io/'
I get warn 'illegal origin ...' but that is just a cloud9 related issue.
Client code:
<html>
<body>
<script src="https://raw.github.com/LearnBoost/socket.io-client/master/dist/socket.io.js"></script>
<script>
var socket = io.connect('http://handsonwithnodejs.samarthwiz.c9.io');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</body>
</html>
I know that using github to get my script isn't the best idea yet, but I wanted to keep my code clean and the error messages readable(everything in 'socket.io.min.js' is on line 2)
P.S. 1. I know that there are other threads like this but they didn't solve my problem.
2. Please don't reply 'Just host the page on the same server as socket.io' I need it to be cross-domain for a reason.
I think you need to set the Access-Control-Allow-Origin header when you host the client code. Look at https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS for more info about the header.
This header must be set by the client for security reasons.
I am completely new to the socket.io and trying to get my feet wet by starting with examples on their home page. But all that i get in console after execution is this
debug - served static content /socket.io.js
My Server side code is this:
var app=require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
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("connected");
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
})
And my index.html goes like this:
var socket = io.connect('document.location.href');
socket.on('error',function(reason){
// console.error("Error");
});
socket.on('connect', function () {
console.log('connected');
socket.send('hi');
socket.on('message', function (msg) {
// my msg
});
});
</script>
I googled about it and couldn't resolve the issue. I am on ubuntu with firefox.
If i'm not mistaken your error is here:
'document.location.href'
which shall be
document.location.href
I've just complete a simple example app for which I'll be soon writing a tutorial:
https://github.com/dotcloud/socket.io-on-dotcloud
You can grab it (just clone it) and fool around with it to easy how to get started with socket.io with express 3. It is even ready to be push on dotCloud if you whish to share your app.
I'm fairly new to node.js and I've found its quite complicated separating a project into multiple files as the project grows in size. I had one large file before which served as both a file server and a Socket.IO server for a multiplayer HTML5 game. I ideally want to separate the file server, socket.IO logic (reading information from the network and writing it to a buffer with a timestamp, then emitting it to all other players), and game logic.
Using the first example from socket.io to demonstrate my problem, there are two files normally. app.js is the server and index.html is sent to the client.
app.js:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
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) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
index.html:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
To separate file server and game server logic I would need the function "handler" defined in one file, I would need the anonymous function used a callback for io.sockets.on() to be in another file, and I would need yet a third file to successfully include both of these files. For now I have tried the following:
start.js:
var fileserver = require('./fileserver.js').start()
, gameserver = require('./gameserver.js').start(fileserver);
fileserver.js:
var app = require('http').createServer(handler),
fs = require('fs');
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);
});
}
module.exports = {
start: function() {
app.listen(80);
return app;
}
}
gameserver:
var io = require('socket.io');
function handler(socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
}
module.exports = {
start: function(fileserver) {
io.listen(fileserver).on('connection', handler);
}
}
This seems to work (the static content is properly served and the console clearly shows a handshake with Socket.IO when the client connects) although no data is ever sent. It's as though socket.emit() and socket.on() are never actually called. I even modified handler() in gameserver.js to add console.log('User connected'); however this is never displayed.
How can I have Socket.IO in one file, a file server in another, and still expect both to operate correctly?
In socket.io 0.8, you should attach events using io.sockets.on('...'), unless you're using namespaces, you seem to be missing the sockets part:
io.listen(fileserver).sockets.on('connection', handler)
It's probably better to avoid chaining it that way (you might want to use the io object later). The way I'm doing this right now:
// sockets.js
var socketio = require('socket.io')
module.exports.listen = function(app){
io = socketio.listen(app)
users = io.of('/users')
users.on('connection', function(socket){
socket.on ...
})
return io
}
Then after creating the server app:
// main.js
var io = require('./lib/sockets').listen(app)
i would do something like this.
app.js
var app = require('http').createServer(handler),
sockets = require('./sockets'),
fs = require('fs');
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);
});
}
sockets.startSocketServer(app);
app.listen(80);
and sockets.js
var socketio = require('socket.io'),
io, clients = {};
module.exports = {
startSocketServer: function (app) {
io = socketio.listen(app);
// configure
io.configure('development', function () {
//io.set('transports', ['websocket', 'xhr-polling']);
//io.enable('log');
});
io.configure('production', function () {
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.set('log level', 1); // reduce logging
io.set('transports', [ // enable all transports (optional if you want flashsocket)
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
});
//
io.sockets.on('connection', function (socket) {
console.log("new connection: " + socket.id);
socket.on('disconnect', function () {
console.log("device disconnected");
});
socket.on('connect_device', function (data, fn) {
console.log("data from connected device: " + data);
for (var col in data) {
console.log(col + " => " + data[col]);
}
});
});
}
};
i just copy&pasted some of my old code - don't really know what changed in the last versions of socket.io, but this is more about the structure than the actual code.
and i would only use 2 files for your purposes, not 3.
when you think about splitting it up further, maybe one other file for different routes ...
hope this helps.
I have had a crack at this as well and I am fairly happy with the result. Check out https://github.com/hackify/hackify-server for source code.
I've another solution. You can use require.js creating a module and pass "app" as an argument. Within the module you can start socket.io and organize your sockets.
app.js:
var requirejs = require('requirejs');
requirejs.config({
baseUrl: './',
nodeRequire: require
});
requirejs(['sockets'], function(sockets) {
var app = require('http').createServer()
, fs = require('fs')
, io = sockets(app);
// do something
// add more sockets here using "io" resource
});
In your socket.js module you can do something like this:
define(['socket.io'], function(socket){
return function(app){
var server = app.listen(3000)
, io = socket.listen(server);
io.sockets.on('connection', function (socket) {
console.log('connected to socket');
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
// more more more
});
return io;
}
});
I hope help you with my contribution.