JS change socket namespace from client when click on button - node.js

I'm developping simple app with nodejs and socket.io.
I created two channels and I want my client connect one of channels when click on button. The problem is I don't get response from server
This is my code :
// SERVER side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendfile('MDC.html');
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
// CLIENT SIDE
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
console.log("setDay");
socket = io.connect('/day');
console.log(socket)
}
socket.on('hiDay',function(data){
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
function setWeek(){
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
}
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
});
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
In my client, I created two button and when I click on one I want change socket namespace

When you call setDay() or setWeek(), you are creating a whole new socket.io connection and thus overwriting your previous socket variable. The socket.on(hiDay, ...) and socket.on('hiWeek', ...) handlers you have are ONLY on the first socket you created, not on the newly created sockets, thus you never see the messages on those.
To fix, add those message handlers only to the right socket after you've connected to that namespace.
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
console.log(data)
});
}
Then, do the same thing for the setDay() function.
And, as shown here you probably want to disconnect the previous connection when changing namespaces too so you don't necessarily leave connections that you aren't using any more.
FYI, you also had a typo where this:
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
should have been this:
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
Final, tested and working code is this:
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
socket.close();
console.log("setDay");
socket = io.connect('/day');
socket.on('hiDay',function(data){
console.log("hiDay")
document.getElementById('message-container').innerHTML = 'Update day';
console.log(data);
});
}
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek");
document.getElementById('message-container').innerHTML = 'Update Week';
console.log(data);
});
}
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
And server code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var path = require('path');
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'socket-io-namespace.html'));
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});

If you create a connect(ns) function you can reconstruct the socket event listener when the namespace changes. The following should work:
<script>
var connect = function (ns) {
return io.connect(ns, {
query: 'ns=' + ns,
resource: "socket.io"
}).on('hiWeek', function (data) {
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
}).on('hiDay', function (data) {
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
}
var socket = io();
function setDay() {
console.log("setDay");
socket = connect('/day');
console.log(socket);
}
function setWeek() {
console.log("setWeek");
socket = connect('/week');
console.log(socket);
}
</script>

Related

Running a socket.io server in a real live server, instead of localhost?

I found a coding from tutorials point to run a a simple socket.io chat server in localhost, I installed necessary environments like nodejs, express, init package.json and I started the server from terminal using command-"node app.js", then I accessed the index page in my localhost it showed the chat page, it is working fine. But the thing is I want to use this is in a live server for my office, to chat within the office. Is this code is enough for that. I am new to this socket.io and nodejs. My office has live server for hosting their website, this code opens and listens to port 3000. It will be highly helpful if you could tell me how to run this in a real server.
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
</head>
<script src = "/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setUsername() {
socket.emit('setUsername', document.getElementById('name').value);
};
var user;
socket.on('userExists', function(data) {
document.getElementById('error-container').innerHTML = data;
});
socket.on('userSet', function(data) {
user = data.username;
document.body.innerHTML = '<input type = "text" id = "message">\
<button type = "button" name = "button" onclick = "sendMessage()">Send</button>\
<div id = "message-container"></div>';
});
function sendMessage() {
var msg = document.getElementById('message').value;
if(msg) {
socket.emit('msg', {message: msg, user: user});
}
}
socket.on('newmsg', function(data) {
if(user) {
document.getElementById('message-container').innerHTML += '<div><b>' +
data.user + '</b>: ' + data.message + '</div>'
}
})
</script>
<body>
<div id = "error-container"></div>
<input id = "name" type = "text" name = "name" value = ""
placeholder = "Enter your name!">
<button type = "button" name = "button" onclick = "setUsername()">
Let me chat!
</button>
</body>
</html>
app.js Server
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res) {
res.sendfile('index.html');
});
users = [];
io.on('connection', function(socket) {
console.log('A user connected');
socket.on('setUsername', function(data) {
console.log(data);
if(users.indexOf(data) > -1) {
socket.emit('userExists', data + ' username is taken! Try some
} else {
users.push(data);
socket.emit('userSet', {username: data});
}
});
socket.on('msg', function(data) {
//Send message to everyone
io.sockets.emit('newmsg', data);
})
});
http.listen(3000, function() {
console.log('listening on localhost:3000');
});
You can solve your problem through nginix( A reverse proxy server). Nginx have .conf file which contains the server realted configuration.
server { listen 3000; server_name io.yourhost.com; }
To run:
Sudo service nginx start
It will start your server on given IP or Domain name.
Change the declaration variable socket by
var socket = io(Server IP + ':port');
Example:
var socket = io('127.0.0.1:3000);
I using socket.io version 2.0.2

How to clear redis database when nodejs server disconnect?

I have a simple chatroom application using a node express server.
This uses a redis database connection to store the nicknames of the joined clients.
I need to clear the redis SET of nicknames named members when the server is closed/disconnected.
This can be done as following:
redisClient.del("members", function(err, reply){
console.log("members set delete :" + reply);
});
But where should I put this code? How to handle the final event from the server when disconnection, from the server side?
Server code - chatroom.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var redis = require('redis');
var redisClient = redis.createClient();
io.on('connection', function(client){
console.log("client connected...");
});
io.on('connection', function(client){
client.on('join', function(name){
client.nickname = name;
//adding names
client.broadcast.emit("add member", name);
redisClient.smembers('members', function(err, names) {
names.forEach(function(name){
client.emit('add member', name);
});
});
client.emit('add member', client.nickname)
redisClient.sadd("members", name);
});
// remove clients on disconnect
client.on('disconnect', function(name){
client.broadcast.emit("remove member", client.nickname);
redisClient.srem("members", client.nickname);
});
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/views/index.html');
});
server.listen(8080);
Client code - views/index.html
<html>
<head>
<title>Socket.io Client</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<h2>Chat box</h2><br>
<h4 id="status"></h4><br>
<div>
<h3>Active members</h3>
<ul id="members"></ul>
</div>
<script>
var socket = io.connect('http://localhost:8080');
socket.on('connect', function(data){
nickname = prompt("What is your nickname?");
$('#status').html('Connected to Chat Room as \''+nickname+'\'.');
socket.emit('join', nickname);
});
socket.on('add member', function(name) {
var member = $('<li>'+name+'</li>').data('name', name);
$('#members').append(member);
});
socket.on('remove member', function(name) {
$('#members li').filter(function() { return $.text([this]) === name; }).remove();
});
socket.on('disconnect', function(data){
$('#status').html('Chatroom Server Down!');
});
</script>
</body>
</html>
How to clear the redis database set when nodejs server disconnect?
you can use error or end events on redisclient, check the Redis Package Documentation
redisClient.on("error", function (err) {
console.log("Error " + err)
// delete here
});
However, since your connection is closed, it is more healthy to delete on first connection to redis each time. do it on reconnection state too.
When a socket.io connection dies, an event named disconnect is fired. Register your reset logic to that callback.
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
redisClient.del("members", function(err, reply){
console.log("members set delete :" + reply);
});
});
});
Credits : How can i handle Close event in Socket.io?

Communicating TCP with HTTP in Socket.io getting TypeError: Cannot read property 'emit' of undefined

Trying to communicate TCP server with HTTP server
My TCP port is 4040 and HTTP port is 3000
I am working on passing data received on TCP server to HTTP server
Data received on TCP port is showing on console window and I am trying to pass this data to HTTP by storing data in global var so that I can display it on the webpage.
Thanks :)
server code:
enter code here var http = require('http').createServer(httpHandler);
var net = require('net');
var app = require('express')(); <!-- These are mandatory variables -->
var http = require('http').Server(app);
var io = require('socket.io')(http);
var sockets = [];
var HOST = 'localhost';
var PORT = 4040;
global.MYVAR = "Hello world";
global.MYVAR2 = "Hello world";
var server = net.createServer();
server.listen(PORT, HOST);
// Keep track of the chat clients
var clients = [];
/**
* http server
*/
function httpHandler (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);
});
}
app.get('/', function(req, res){ <!-- This sends the html file -->
//send the index.html file for all requests
res.sendFile(__dirname + '/index.html');
});
http.listen(3000, function(){ <!-- Tells the HTTP server which port to use -->
console.log('listening for HTTP on *:3000'); <!-- Outputs text to the console -->
console.log('listening for TCP on port ' + PORT);
});
<!-- everything below this line is actual commands for the actual app -->
io.on('connection', function(socket) // Opens the socket
{
socket.on('checkbox1', function(msg){ // Creates an event
console.log(msg); // displays the message in the console
MYVAR = msg; // Sets the global variable to be the contents of the message recieved
for (var i = 0; i < sockets.length; i++) {
if(sockets[i]) {
sockets[i].write(MYVAR, 'utf-8');
}
}
});
});
server.on('connection', function(socket){ // Opens the socket for the TCP connection
sockets.push(socket);
socket.write(MYVAR, 'utf-8');
// Handle incoming messages from clients.
socket.on('data', function (data) {
broadcast(socket.name + "> " + data, socket);
});
// Send a message to all clients
function broadcast(message, sender) {
MYVAR2 = message;
console.log(MYVAR2);
socket.broadcast.emit('updateHeader',MYVAR2); // GETTING ERROR HERE
}
}).listen(PORT, HOST);
index.html code:
<!doctype html>
<html>
<head>
<title>Socket IO Test</title>
</head>
<body>
<h1 id="h1">Hello World</h1>
<form action="">
<input type='checkbox' onclick='checkbox1(this);'>Checkbox1</label>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
var number = 0;
$(document).ready(function(){
socket.on('updateHeader',function(data){
console.log('updateHeader called');
document.getElementById('h1').innerHTML = data;
});
});
function checkbox1(cb) {
socket.emit('checkbox1', 'checkbox 1 = ' + cb.checked);
return false;
}
</script>
The problem is you're trying to use socket.io broadcast in a net.Socket which of course doesn't have that property.
server.on('connection', function(socket){ /* ... */ }
When a new TCP stream is established. socket is an object of type
net.Socket. Usually users will not want to access this event. In
particular, the socket will not emit 'readable' events because of how
the protocol parser attaches to the socket. The socket can also be
accessed at request.connection.
I don't know exactly what you're trying to achieve, but you can use io.emit if you want to send message to all clients.
function broadcast(message, sender) {
MYVAR2 = message;
//This will emit 'updateHeader' to all socket.io connected sockets
io.emit('updateHeader', MYVAR2);
//The 'socket' you were using here was a net.Socket not a socket.io one.
}
function broadcast(message, sender) {
MYVAR2 = message;
console.log(MYVAR2);
sender.broadcast.emit('updateHeader',MYVAR2); //Replace socket by sender here
}

Socket.io client does not connect to server

I am trying to make a Node.js app that will have an embedded chat. I am using socket.io to create that chat. I have attempted to set up my server / client, but the client does not seem to be connecting. I have my application to set log when sockets connect and disconnect but it never seems to log anything. I figured that the client was being retarded so I opened the Chrome devtools, and typed in:
var socket = io();
oddly, I start seeing a string of failed requests that look like:
GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=1434334401655-37 404 (Not Found)
So now I'm sure it s my server. here is my server code:
var express = require("express");
var mongoose = require("mongoose");
var io = require("socket.io").listen(app);
// var restAPI = require("./api");
// Set up the application.
var app = express();
app.use(express.static("static"));
// Mount up the rest API
// app.use("/rest", restAPI);
// Default index route.
app.get("/", function(req, res) {
res.sendFile(__dirname + "/index.html");
});
// This will maintian a transcript of the chat
var transcript = []
// This route will return the transcript data as json
app.get("/transcript", function(req, res) {
res.json(JSON.stringify(transcript));
});
// Simple socket.io for chat application
// Lets keep a reference to how many connections we have
var count = 0;
io.sockets.on("connection", function(socket) {
// Increment the number of clients
count++
// Keep a reference to the socket
var current = socket;
// Log the connection
console.log("Connected to: " + current + " at " + Date.now() + ".");
// Log the current number of users
console.log("There are now " + count + "users connected.");
// Handle disconnection
socket.on("disconnect", function() {
// Same routine as connect
console.log(current + ": disconnected at " + Date.now() + ".");
console.log("There are now " + count + "users connected.");
});
});
app.listen(3000);
Here is my HTML client:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport">
<title>Paint</title>
<!-- <script src="/js/application.js"></script> -->
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
</head>
<body>
<header></header>
<nav></nav>
<aside>
<div id="toolbox"></div>
<!-- display: none; by default -->
<div id="chat"></div>
<div class="buttons">
<div class="toolBoxButton">Toolbox</div>
<div class="chatButton">Chat</div>
</div>
</aside>
<section></section>
<footer></footer>
<script>
var socket = io();
</script>
</body>
</html>
Why can't the client connect?
I don't know if this is the only issue, but you're calling this:
var io = require("socket.io").listen(app);
before you assign the app variable so it is undefined.
The request for this URL:
http://localhost:3000/socket.io/?EIO=3&transport=polling&t=1434334401655-37
is how a socket.io connection starts so that is normal. The problem is that the socket.io listener wasn't running properly on the server so nothing was listening for that route.
Also, I don't know if this:
io.sockets.on("connection", function(socket) {...});
works in socket.io v1+. The socket.io doc says to use this:
io.on('connection', function(socket) {...});

socket.io server not listening

I'm using node.js and socket.io for a simple app. My browser is receiving data from server nicely but server not receiving from client(browser). May be the event listener for client_data not working. Here is the server:
var http = require("http");
var url = require("url");
var io = require('socket.io');
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(pathname, response);
}
var server = http.createServer(onRequest);
server.listen(8888);
var server_io = io.listen(server);
server_io.on('connection', function(socket){
//send data to client
setInterval(function(){
socket.emit('date', {'date': new Date()});
}, 1000);
});
//recieve client data
server_io.on('client_data', function(data){ //May be it is not listening
process.stdout.write(data.letter); // not working
//console.log(data.letter); not working
});
console.log("Server has started.");
}
exports.start = start;
Client code:
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<script>
var socket = io.connect();
socket.on('date', function(data){
document.getElementById("date").innerHTML = data.date;
});
function sendKey(e){
socket.emit('client_data', {'letter': String.fromCharCode(e.charCode)});
}
</script>
<div id="date">This is our socket.html file</div>
<textarea id="text" onKeyPress="sendKey(event)"></textarea>
</body>
</html>
What is the problem with my server code?
This error occurs because .on('client_data') must be binded to socket, not server_io. The code may look like the following:
server_io.on('connection', function(socket){
setInterval(function(){
socket.emit('date', {'date': new Date()});
}, 1000);
socket.on('client_data', function(data){
process.stdout.write(data.letter);
});
});
server_io only recieves connection events. The client_data event sent from the client is heard by the socket object passed into the connection callback, not the server_io object.
You need to use socket.on("client_data", ...); and move that code into your connection callback.
That socket object is connected to a particular client web page instance, and it recieves messages only sent by that page. Each time a new client page connects, a new socket object is created and passed as an argument into the connection handler function.

Resources