I am creating a WebSocket for an online game. I have some code that works perfectly, but after a time the server stops the Socket. I don't know what can be wrong and I don't have an error or something. It just stops running.
Does anyone know what can be wrong with this code?
var mysql = require('mysql');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var cookies;
var db = mysql.createConnection({
host: 'hostname',
user: 'username',
password: 'password',
database: 'database',
port: 3306
});
db.connect(function(err){
if (err) console.log(err)
});
function createCookie(name,value,days, socket) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
socket.handshake.headers['cookie'] = name+"="+value+expires+"; path=/";
}
function readCookie(name, socket) {
var nameEQ = name + "=";
var ca = socket.handshake.headers['cookie'].split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name, socket) {
createCookie(name,"",-1, socket);
}
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
socket.on('chat message', function(msg){
if(readCookie('uid', socket) != null) {
db.query('SELECT * FROM ww_user_settings WHERE usr_set_id = '+readCookie('uid', socket)+' AND usr_set_setting_id = 23').on('result', function(data){console.log('Message from '+data.usr_set_value+': '+msg);io.emit('chat message', data.usr_set_value+": "+msg);});
}
else {
console.log('Unauthorized message sent.');
socket.disconnect('unauthorized');
}
});
});
http.listen(44444, function(){
console.log('listening on *:44444');
});
As I said, the Socket works. But after a time, even when nothing special happens, the Socket stops running on my Windows 2012 Server.
The problem here was that the server lost the connection with the MySQL Server. By losing it, it will stop working.
Related
I have a node server code on named server.js
var env = require('dotenv').config({path: '../.env'});
var fs = require("fs");
var options = {
key: fs.readFileSync(env.APP_SSL_PATH + 'server.key').toString(),
cert: fs.readFileSync(env.APP_SSL_PATH + 'server.crt').toString()
};
var app = require('express')();
var http = require('https');
var server = http.createServer(options, app);
var io = require('socket.io')(server);
var redis = require('redis');
// Check if server is listening on its port
server.listen(env.APP_NODE_PORT, function() {
console.log('Listening on your port');
io.on('connection', function (socket) {
console.log("new client connected");
var redisClient = redis.createClient();
redisClient.subscribe('notification-channel', function(err, count) {
});
redisClient.on("message", function(channel, message) {
console.log( " message= "+ message + " channel = " + channel);
socket.emit(channel, message);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
});
Using http it works fine but then when I add the SSL certificate on https the code is not working already and it doesn't throw any error. I run the node server.js by
node server.js > stdout.txt 2> stderr.txt
there are no error log showing on stderr.txt file. Please help me Im new on this. On the console
Listening on your port
will logged only it does not continue and log
new client connected
This is my client side code:
<script>
var socket = io.connect('{{ env("APP_URL") }}:8890');
socket.on('notification-channel', function (data) {
var header_count_elem = $('#menubar #header-messages-count');
var count = header_count_elem.text();
if (data != 'no-sound') {
$.get('/notification/notif-alerts', function(response) {
header_count_elem.text((response.count == '0') ? '' : response.count);
if (data != 'no-sound') {
if (count != response.count) {
var sound = '<audio id="audioplayer" autoplay=true volume=1>' +
'<source src="{{ url('assets/themes/cpanel/alarms/notification_sound.mp3') }}" type="audio/mpeg">' +
'<source src="{{ url('assets/themes/cpanel/alarms/notification_sound.ogg')}}" type="audio/ogg">' +
'</audio>';
$('body').append(sound);
}
}
});
}
});
Socket IO server is running fine on single instance of NodeJs. But when I'm using cluster module of NodeJS to run the servers on multiple cores I'm getting the error, "Connection closed before receiving a handshake response". I've googled the reason and found out that,
Essence of the problem is, when you run multiple Node app threads (workers) on a server, or multiple servers, socket.io clients connections are routed by cluster in a random round-robin manner, and handshaken / authorized io client requests get handed to workers where they are not handshaken / authorized, where the mess begins. Source Link
I've tried a couple of things to make it work but no success so far. Here's the code
'use strict';
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var express = require('express');
var config = require('./config/environment');
var session = require('express-session');
var redisStore = require('connect-redis')(session);
var cluster = require('cluster');
var domain = require('domain');
var socketIo = require('./config/socketio');
var REDIS = require('redis')
var store = REDIS.createClient();
var pub = REDIS.createClient();
var sub = REDIS.createClient();
if(cluster.isMaster) {
var numWorkers = require('os').cpus().length;
for(var i = 0; i < numWorkers; i++) {
cluster.fork();
}
} else {
var d = domain.create ();
d.on ("error", function (error){
// start new server
});
// Setup server
var app = express();
var server = require('http');
d.run (function (){
server = server.createServer(app);
});
require('./config/express')(app);
require('./config/redis')();
require('./routes')(app);
server.listen(config.port, config.ip, function () {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
});
var redis = require('socket.io-redis');
var socketIO = require('socket.io')(server, {
serveClient: (config.env === 'production') ? false : true,
path: '/socket.io-client'
});
sub.subscribe('chat');
socketIO.adapter(redis( {host: 'localhost', port: 6379}));
socketIo.createSocketConnection('/dummy', socketIO, sub, pub, store);
exports = module.exports = app;
}
File: ./config/socketio
'use strict';
function addNamespaceForId (socketio, namespace, sub, pub, store){
socketio.of(namespace).on('connection', function(socket) {
onConnect(socketio, socket, namespace, sub, pub, store);
console.info('[%s] CONNECTED', socket.address);
sub.on('message', function(pattern, key){
store.hgetall(key, function(e, obj){
socket.send(obj.uid + ": " + obj.text)
})
})
socket.on('disconnect', function() {
console.info('[%s] DISCONNECTED', socket.address);
});
});
}
}
function onConnect(io, socket, namespace, sub, pub, store) {
socket.on('message', function(from, msg) {
store.incr("messageNextId", function(e, id){
store.hmset("messages:" + id, { uid: socket.sessionId, text: 'text;' }, function(e, r){
pub.publish("chat", "messages:" + id)
})
})
io.emit('broadcast', {
payload : from['message'],
source : from
});
io.of(namespace).emit('broadcast', {
payload : from['message'],
source : from
});
});
// When the client emits 'info', this listens and executes
socket.on('info', function(data) {
console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
});
// Insert sockets below
require('../api/thing/thing.socket').register(socket);
}
module.exports = {
createSocketConnection : function (namespace, socketio, sub, pub, store){
addNamespaceForId(socketio, namespace, sub, pub, store);
}
};
I've also tried using adapter for redis as suggested in the documentation.
This setup works sometimes but not always. I'm unable to figure out the missing point.
I'm trying to make a simple IRC to get to understand how things work. I've set up a local node server and another workspace to connect to localhost, they talk just fine. However when I push the local server to Openshift and try to connect to it with the client with;
var socket = io.connect("http://irc-abc.rhcloud.com:3000");
It's not connecting.
What am I doing wrong here and or how can I make this work?
NOTE: I'm new to websockets and I'm trying to understand them, I'm probably missing the big picture.
Yes I did find a lot of similar questions on stackoverflow however it did not help me, as I said I'm fairly new with websockets and have some trouble understanding it.
server
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var ip = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';
var port = process.env.OPENSHIFT_NODEJS_PORT || 3000;
// TO-DO verify creds against db
var credentials = {
'username' : ''
};
io.on('connection', function(socket){
// verify if client has username
socket.on('login', function(credentials){
if(credentials.username) {
this.username = credentials.username;
console.log( this.username + ' connected');
io.emit('notice', this.username + ' connected');
}
else {
console.log( 'USER GOT DENIED' );
socket.disconnect();
}
// when message received
socket.on('chat message', function (msg) {
var message = this.username + ': ' + msg;
io.emit('chat message', message);
});
});
// when user disconnects
socket.on('disconnect', function(){
console.log( this.username + ' disconnected');
});
});
http.listen(port, ip);
console.log('listening on ' + ip + ':' + port);
Client
var socket = io.connect("irc-abc.rhcloud.com:3000");
var username = '<?php if(isset($_SESSION['username'])) echo $_SESSION['username'];
else echo 'guest'; ?>';
var credentials = {
'username' : username
};
socket.emit('login', credentials);
$('form').submit(function() {
if ($('#m').val()) {
socket.emit('chat message', $('#m').val());
$('#m').val('');
}
window.scrollTo(0,document.body.scrollHeight);
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
window.scrollTo(0,document.body.scrollHeight);
});
socket.on('notice', function(notice){
$('#messages').append($('<li>').text(notice));
window.scrollTo(0,document.body.scrollHeight);
});
The first thing I'd do is check if port 3000 is firewalled. Some (most) hosts firewall all ports that are not normally used (80, 443, etc). If you can't get them to change the firewall right away, test with port 80.
I'm using Node & Express 4.0 deployed on Heroku, and I'm trying to implement Socket.io with Redis as aa session store. So I have this as my current code:
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var RedisStore = io.RedisStore;
if (process.env.REDISTOGO_URL) {
// inside if statement
var rtg = require("url").parse(process.env.REDISTOGO_URL);
var redis = require("redis").createClient(rtg.port, rtg.hostname);
redis.auth(rtg.auth.split(":")[1]);
} else {
var redis = require("redis").createClient();
}
/** Initialize RedisStore for socket.io **/
io.set('store', new RedisStore({
redis : redis
}));
But I get the following error:
14:25:03 web.1 | io.set('store', new RedisStore({
14:25:03 web.1 | ^
14:25:03 web.1 | TypeError: undefined is not a function
I've also seen this way of defining a RedisStore:
var redis = require('socket.io/node_modules/redis');
var RedisStore = require('socket.io/lib/stores/redis');
However, my installed version of socket.io, installed using npm install --save socket.io, doesn't include stores in the lib directory:
EDIT
I saw this on the socket.io page in regards to their 1.0 release:
// 2. Implement the socket.io-redis adapter
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
But there's no other documentation I could find regarding this new module, and since I'm new to this whole stack, I don't think I could figure it out on my own.
The trend among node.js modules is to remove functionality that isn't truly core to the module.
Which is why socket.io 1.0 no longer supports redis out of the box.
So step one is to track down the functionality you need.
http://socket.io/docs/server-api/
https://github.com/Automattic/socket.io-adapter
https://github.com/Automattic/socket.io-redis
Then you need to install the other module npm install socket.io-redis --save
And finally configure your app.
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');
io.adapter(redis(process.env.REDISTOGO_URL));
The nice part is the socket.io-redis adapter accepts redis urls and defaults to localhost:6379 so you (should) be able to simple pass in the REDISTOGO_URL
I had to parse libraries above to get this example, so I figured I would post a full blown example, but I must admit there are a couple of things off, this uses REDISCLOUD, it is on Heroku, it does work. I'll post this elsewhere and maybe put it in a doc too.
var redis = require('redis');
var ioredis = require('socket.io-redis'); //Adapter
var url = require('url');
var redisURL = url.parse(process.env.REDISCLOUD_URL );
var pub = redis.createClient(redisURL.port, redisURL.hostname, {return_buffers: true});
var sub = redis.createClient(redisURL.port, redisURL.hostname, {return_buffers: true});
pub.auth(redisURL.auth.split(":")[1]);
sub.auth(redisURL.auth.split(":")[1]);
var redisOptions = {
pubClient: pub,
subClient: sub,
host: redisURL.hostname,
port: redisURL.port
};
io.adapter(ioredis(redisOptions));
Following code works for me with Heroku Redis, hope this helps.
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
var redisAdapter = require('socket.io-redis');
io.adapter(redisAdapter({
pubClient: redis.createClient(process.env.REDIS_URL, {return_buffers: true}),
subClient: redis.createClient(process.env.REDIS_URL, {return_buffers: true})
}));
For the ones interested,
this is my prototype chat server running on newest socket.io with express, multiple cores and redis as an intermediate.
Broadcasted messages are send to all room users no matter if they are connected to a different node and port instance.
Just run
node server.js
and on other machines
node client.js
or for testing node client.js 7001, 7002, 7003 ......
server.js
var options = {
//workers: 2, // total workers (default: cpu cores count).
first_port: 7000, // 8000, 8001 are worker's ports (default: 8000).
proxy_port: 5000, // default (5000).
session_hash: function (req, res) { return req.connection.remoteAddress; },
no_sockets: false // allow socket.io proxy (default: false).
};
require('sticky-socket-cluster')(options, start);
function start(port) {
// requirements
var express = require('express');
var http = require('http');
var socketio = require('socket.io');
var path = require('path');
var sticky = require('sticky-session');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
server.listen(port, function() {
console.log(' - listening on ' + port+ ' ' + __dirname);
});
// require our chatserver
var ChatServer = require('./chatserver');
// initialize a new chat server.
new ChatServer({io: io, port: port}).init();
}
chatserver.js
RoomUtil = (function(){
roomMessages = {};
return {
getMessages : function(room_id,limit,cb){
//TODO
cb(roomMessages[room_id] || []);
},
postMessage : function(message,room_id,cb){
if (!roomMessages[room_id]) roomMessages[room_id] = [];
roomMessages[room_id].push(message);
cb();
}
}
})();
var Server = function(options) {
var self = this;
self.io = options.io;
// users array
self.users = [];
// initialize function
self.init = function() {
console.log("init");
// Fired upon a connection
self.io.on('connection', function(socket) {
console.log("incoming connection");
// var ru = new RoomUser();
self.handleConnection(socket,options.port);
});
}
// socket handler for an incoming socket
self.handleConnection = function(socket,port) {
// wait for a login message
socket.emit("incoming connection",{});
socket.on("joinroom",function(data,joinroom_callback){
console.log("attempt to join room ",data.room_id," on port ",port);
if (!data.room_id){
console.log("cannon join room -> no room id given");
return socket.disconnect();
}
else{
var room_id = data.room_id;
socket.join(room_id,function(){
console.log(socket.rooms);
RoomUtil.getMessages(data.room_id,50,function(messages){
console.log("client succesfully joined room ",data.room_id);
joinroom_callback(null,{'messages':messages});
});
socket.on("login",function(data,login_callback){
if (!data.username){
login_callback("invalid userdata",null);
}
else{
login_callback(null,1);
socket.on("post_message",function(data,message_callback){
if (!data.message || data.message == ""){
console.log("empty message posted. ignore");
message_callback("invalid_message",null);
}
else{
console.log("received message on port ",port,data.message);
message_callback(null,1);
RoomUtil.postMessage(data.message,room_id,function(){
RoomUtil.getMessages(room_id,50,function(messages){
console.log("emit messages to room id ",room_id);
//socket.to(room_id).emit('update_messages', messages);
//socket.broadcast.to(room_id).emit('update_messages', messages);
//socket.broadcast.to(room_id).emit('update_messages', messages);
//self.io.to(room_id).emit('update_messages', messages);
self.io.in(room_id).emit('update_messages', messages);
});
})
}
});
}
});
});
}
});
}
}
module.exports = Server;
client.js
var servercon = 'http://localhost:'+(process.argv[2] || 5000);
console.log("going to connect to "+servercon)
var socket = require('socket.io-client')(servercon);
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
socket.on('connect', function(){
console.log("connected, going to login");
socket.emit("joinroom",{"room_id":123123}, function(error,data){
if (error){
console.log("cannot join room ",error);
}
else{
console.log("succesfully joined room -> going to login now");
console.log("received messages count",data.messages.length);
socket.emit("login",{username:"John Mckain"}, function(error, message){
if (error){
console.log("error logging in ",error);
}
else{
console.log("logged in succesfully -> post message now");
var readline = function(){
rl.question("type in a message -> ", function(message) {
socket.emit("post_message",{'message':message}, function(error, message){
if (error){
console.log("error posting message");
readline();
}
else{
console.log("succesfully posted message");
readline();
}
});
});
}
readline();
}
});
socket.on("update_messages",function(data){
console.log("received new messages count ",data.length,data);
});
}
});
});
socket.on('event', function(data){
console.log("event send",data);
});
socket.on('disconnect', function(e){
console.log("disconnected",e);
});
socket.on("welcome",function(data){
console.log("on welcome ",data)
})
socket.on("pong",function(e){
console.log("pong")
})
I'm trying to build a simple Node app using Express, Socket.io, and the ntwitter module so you can just search for a term (that's req.params.searchTerm below) and ntwitter will search for it and output the stream via socket.io.
I'm running into errors, though, with multiple windows open, or closing a window and then opening a window immediately afterwards. Sometimes the search term is not updated, sometimes some kind of socket.io error is actually thrown. Could someone clarify the right way to do this or shed some light to my error? Thanks in advance. Code below.
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
app.get('/:stream', function(req, res) {
res.render('stream', { title: 'Search Twitter | ' + req.params.searchTerm });
io.sockets.on('connection', function(socket) {
var publishFlag = true;
setInterval(function() {
publishFlag = true;
}, 1000);
twit.stream('statuses/filter', { track: [req.params.searchTerm] },
function(stream) {
stream.on('data', function(tweet) {
if(publishFlag) {
socket.emit('tweet', tweet);
publishFlag = false;
}
});
}
);
});
});
It think that is somewhat what you are trying to do :
Server side :
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
app.get('/:stream', function(req, res) {
res.render('stream', { title: 'Search Twitter | ' + req.params.searchTerm });
});
io.sockets.on('connection', function(socket) {
socket.on('stream', function(searchTerm){
twit.stream('statuses/filter', { track: [searchTerm] },
function(stream) {
stream.on('data', function(tweet) {
socket.emit('tweet', tweet);
});
}
);
};
});
client side (/:stream)
var socket = io.connect('http://localhost');
socket.on('tweet', addTweetOnPage);
socket.emit('stream', searchTerm);