Socket.io return null as data but server is receiving the data - node.js

I am new at nodes, express, mongodb and socket.io. Things have been working pretty smooth up and till now. So i am building this small test application where the user inputs his name and then post a question.
The socket.io receives the data (username and question) but upon returning the data is says null. (In the beginning it was working but then i started with installing mongoose and things went wrong from that point on). I work with the express framework and all the necessary modules are installed.
in my views this is the code for connection to socket and updating the data:
<script>
$(document).ready(function()
{
var socket = io();
$("#btnAskQuestion").on("click", function(e)
{
//get the value of the inputfield and textarea
var username = $('#inputQuestion').val();
var question = $('#question').val();
var result = "<p>Username: </p>" + username + " <br /><br /> " +
"<p>Question: </p>" + question + " <br /> <br /> ";
console.log("Values of inputfield & textarea: " + result);
//makes the connection to the server and send the data
var socket = io.connect('http://localhost:3000');
socket.emit('sendQuestion', result);
console.log("Gets send: " +result);
//alert('test');
});
//returns the updated data + visualize it on the page
socket.on('updateQuestion', function (data)
{
console.log("Updated data: " + data);//data is the username and question = result
$('#answer').css("border", "4px solid #9C27B0");
$('#answer').css("borderRadius", "8px");
$('#answer').css("padding", "10px");
$('#answer').css("fontSize", "16px");
$('#answer').append('<li>'+data+'</li>');
});
});
</script>
in my bin>www file i have the following code for the server-side connection:
var io = require('socket.io')(server);
io.on('connection', function (socket)
{
socket.on('sendQuestion', function (data)
{
console.log("The server received a question");
console.log(data);
// send question to ALL clients
io.sockets.emit("updateQuestion", data.result);
});
});
In chrome browser i run the developer tools and the output is the following screenshot:
http://www.nappdev.be/clientside.png
This is a screenshot from the server-side where it logs the data
http://www.nappdev.be/serverside.png
I hope somebody can help me out because i don't see why its returning null
Thanks in advance !!1

[edited: just noticed that you are actually sending data.result which is null in the first place]
Instead of sending data.result send data.
Note that this will give you the whole string (username + question). If you only want the question, you will have to parse the received string on the server side and emit only the question to the connected clients.

Related

socket io doesn't work both way?

My current problem is that there are two browsers (two users). Once both of them are connected, they could do a certain socket event which is a friends Request but not both at the same time. Always need to refresh one of the user's page.
Illustratively
When a user click this button
the navbar glyphicon will be incremented by 1
Serverside event
io.on('connection', function(socket){
// Everytime user is connected, I will do some Database operation to store the socketId, it will look something like this
user.socketId = socket.id; // For simplicity.
console.log(socket.request.user.username); // is using passport-socket.io library
socket.on('friendsRequest', function(data) {
// Got these two datas from input hidden on html by using Jquery
var socketId = data.socketId;
var userId = data.userId;
socket.to(socketId).emit('friendsRequest', socket.request.user);
console.log("Successful" + " from " + socket.request.user.username);
});
The weird thing is , on the serverside it is always showing console.log("Successful" + " from " + socket.request.user.username); meaning if click the button on both User's browser it will show correctly
"Successful from UserA"
"Successful from UserB"
But the problem is on the clientside, the targeted html never changed, it always one of the browser navbar's glyphicon will be incremented
Here's the code on the client side
// This event will send the targeted data like socketId and userId back to the server
$(document).on('click', "#addFriend", function(e){
e.preventDefault();
var userId = $('#userId').val();
var socketId = $('#socketId').val();
socket.emit('friendsRequest', {
userId: userId,
socketId: socketId
});
});
// Once the server has done doing his job, this event will listen.
socket.on('friendsRequest', function(data) {
var totalRequests = parseInt($('#totalRequests').html());
console.log(totalRequests);
totalRequests += 1;
$('#totalRequests').html(totalRequests);
$('#friendsRequested').append('<li>' + data + '</li>');
});
The main problem is on the clientside socket.on('friendsRequest');
It only works of one of the browsers but not both at the same time when I fired the friendsRequest event
Need someone with socket.io expertise to explain to me why it doesn't work both ways. As to my logic it is supposed to work.
html
<input type="hidden" name="socketId" id="socketId" value="ValueOftheSocketId" />
<button type="submit" id="addFriend" class="btn btn-default">Add Friend</button>
If the event 'friendsRequest' is not fired the error always will be when you emit it on server:
socket.to(socketId).emit('friendsRequest', socket.request.user);
It is probably that the socketId is not the correct, why? :
The socket.id is reset when a reconnection occurs. So that probably would cause that when you do: socket.to(socketId).emit('friendsRequest', socket.request.user);
it is sent anyone.
A reconnection can happen when a error occurs inside a event listener on client (it will not appear on console).
So for watch if that happens you can use the default event 'disconnect' on server:
socket.on('disconnect', function () {
console.log('user disconnected');
});

Chat App using Socket.io and Node.js

I am developing chat app using Node.js and Socket.io.
Here is my code.|
socket.js
var io = require('socket.io').listen(8001);
var http = require('http');
var url = require('url');
var fs = require('fs');
// open the socket connection
io.sockets.on('connection', function (socket) {
// listen for the chat even. and will recieve
// data from the sender.
socket.on('chat', function (data) {
// default value of the name of the sender.
var sender = 'unregistered';
// get the name of the sender
socket.get('nickname', function (err, name) {
console.log('Chat Message By: ', name);
console.log('error ', err);
sender = name;
});
// broadcast data recieved from the sender
// to others who are connected, but not
// from the original sender.
socket.broadcast.emit('chat', {
msg : data,
msgr : sender
});
});
// listen for user registrations
// then set the socket nickname to
socket.on('register', function (name) {
// make a nickname paramater for this socket
// and then set its value to the name recieved
// from the register even above. and then run
// the function that follows inside it.
socket.set('nickname', name, function () {
// this kind of emit will send to all! :D
io.sockets.emit('chat', {
msg : "Hello " + name + '!',
msgr : "Mr.Server"
});
});
});
});
index.html
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script>
var name = '';
var socket = io.connect('http://localhost:8001');
// at document read (runs only ones).
$(document).ready(function(){
// on click of the button (jquery thing)
// the things inside this clause happen only when
// the button is clicked.
$("button").click(function(){
// just some simple logging
$("p#log").html('Sent message: ' + $("input#msg").val());
// send message on inputbox to server
socket.emit('chat', $("input#msg").val() );
$("p#data_recieved").append("<br />\r\n" + name + ': ' + $("input#msg").val());
// then we empty the text on the input box.
$("input#msg").val('');
});
$("#btnSubmit").click(function(){
alert("Disconnected");
//socket.clients[kickedUserSocketId].onDisconnect();
socket.close();
});
// ask for the name of the user, ask again if no name.
while (name == '') {
name = prompt("What's your name?","");
}
// send the name to the server, and the server's
// register wait will recieve this.
socket.emit('register', name );
});
// listen for chat event and recieve data
socket.on('chat', function (data) {
// print data (jquery thing)
$("p#data_recieved").append("<br />\r\n" + data.msgr + ': ' + data.msg);
// we log this event for fun :D
$("p#log").html('got message: ' + data.msg);
});
socket.emit('forceDisconnect');
</script>
</head>
<body>
<input type="text" id="msg"></input>
<button>Click me</button>
<p id="log"></p>
<p id="data_recieved"></p>
</body>
<input id = "btnSubmit" type="submit" value="Disconnect"/>
</html>
I am running first socket.js from command prompt. After that, I am running .html file in browser 2 times. Now 2 users can chat via browsers. But when I am trying to put my .js file and .html file on server which I have created using FileZila and running .js file, it is running but when I am trying to run .html file on server side(In this case FileZila) , by giving the IP address and Port number of server it is not running. Can you tell me what is the problem?
This doesn't seem to be a nodejs-issue.
You have a server that should be reachable by IP with something like 'http://your.domain.or.ip:80'.
If you get a "can't connect" in your browser then make sure there is no firewall in its way and that port (in the example: 80) is reachable from your browser location (aka known as "your pc"). Please note that you have your socket-service on port 8001 and your web server maybe runs on a different port? Make sure both ports are open.
If you get a blank page, check the browser javascript error messages.
There is a chance that you forgot to upload the file 'socket.io.js' in that directory '/socket.io/'. Try to download that file directly to see if your server serves.

socket.io get data from onclick action then pass the data to other pages to execute the data

I want to create a page using node.js and socket.io.
There are two buttons inside the page, when I click one of them, it will change a variable which defines the animation-duration(I omit the CSS animation codes here).
When I open the same page on another web-browser and click one of the buttons, I hope to see the change in both of the webpages. I don't know how to write the code inside the socket.on('chat', function(data){???}); to make two pages communicate with each other.
Client side:
//socket.io codes--
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://localhost:3000');
socket.on('chat', function (data)
{
function change_position(data)
{
document.getElementById("animation1").style.WebkitAnimationDuration=data;
}
});
</script>
.....
//action--
<body>
<button id="1b" type="button" style="position:absolute; left:377px; top:220px;" value="2s"; onclick="change_position(value)"> - 1 - </button>
<button id="2b" type="button" style="position:absolute; left:477px; top:220px;" value="15s"; onclick="change_position(value)"> - 2 - </button>
</body>
server side:
var io = require('socket.io'),
connect = require('connect');
var app = connect().use(connect.static('public')).listen(3000);
var chat_room = io.listen(app);
chat_room.sockets.on('connection', function (socket) {
socket.on('chat', function (data) {
chat_room.sockets.emit('chat', data);
});
});
If your want a message to propagate to all clients/sockets, in your server you should have something like:
chat_room.sockets.on('connection', function (socket) {
socket.on('chat', function (data) {
socket.broadcast.emit('chat', data);
socket.emit('chat',data);
});
});
The line socket.emit('chat',data); allows you to send the message back also to the sender of it, because broadcast will send it all other sockets.
Of course, you could ommit that line and handle the message sending logic in the client; i.e. adding some JavaScript code that makes the changes you want just after sending the message to the server.
You can emit on your client using socket.emit('message', data). Then on the server get it with chat_room.socket.on('message', data). Emit it to the clients using chat_room.sockets.emit('message', data).

Sending message to specific client with socket.io and empty message queue

I´m going crazy with socket.io!
Documentation is so bad it's simply not true.
I want to send a feedback to specific client over socket.io
My server side looks like this:
app.get('/upload', requiresLogin, function(request, response) {
response.render('upload/index.jade');
io.sockets.on('connection', function (socket) {
console.log('SOCKET ID ' + socket.id);
io.sockets.socket(socket.id).emit('new', 'hello');
});
});
and the client side looks like this:
$(document).ready(function() {
var socket = io.connect('http://localhost:80/socket.io/socket.io.js');
socket.on('new', function (data) {
console.log(socket.id);
console.log(data);
//$('#state').html(data.status);
});
});
but the client does simply nothing. I have tried nearly everything. Can someone tell me what I am doing wrong, please! :(
to send a message to a specific client save every one that connects to the server in an Object.
var socketio = require('socket.io');
var clients = {};
var io = socketio.listen(app);
io.sockets.on('connection', function (socket) {
clients[socket.id] = socket;
});
then you can later do something like this:
var socket = clients[sId];
socket.emit('show', {});
A couple of ways to send feedback to a specific client over socket.io include:
As stated by pkyeck, save all clients to an Object, so you can send to these specific clients later in your route handlers, e.g.:
var sessionsConnections = {};
sio.on('connection', function (socket) {
// do all the session stuff
sessionsConnections[socket.handshake.sessionID] = socket;
});
or, use socket.io's built in support for rooms - subscribe each client to a room on connection and send via this room within route handlers, e.g.:
sio.on('connection', function (socket) {
// do all the session stuff
socket.join(socket.handshake.sessionID);
// socket.io will leave the room upon disconnect
});
app.get('/', function (req, res) {
sio.sockets.in(req.sessionID).send('Man, good to see you back!');
});
Acknowledgement:
http://www.danielbaulig.de/socket-ioexpress/#comment-1158
Note that both these example solutions assume that socket.io and express have been configured to use the same session store and hence refer to the same session objects. See the links above and below for more details on achieving this:
https://github.com/LearnBoost/socket.io/wiki/Authorizing
2 things
1) You should really place your io.sockets.on(..) outside your app/update route to prevent adding multiple listeners for clients.
2) io.sockets.socket(id); should not be used, it should have been socket.emit('new', 'hello')
In socket.io 1.0, this is how it would work. It may work for lower versions, but I cannot guarantee it.
socket.to(socket_id_here).emit('new', 'hello');
This works because socket.io automatically adds a socket to a room with the socket's id on connection.
Also, if you plan to upgrade to version 1.0, there are a lot of changes to the api, so you'll sometimes have to change some code to make it work in 1.0.
The correct way to do this in Socket.io 1.0+ is:
io.to(users_socket_id).emit('new', 'hello');
You can also substitute a room name for 'users_socket_id' to emit to a specific socket.io room.
First of all, you cannot use socket.id on client side.
And then change the line
var socket = io.connect('http://localhost:80/socket.io/socket.io.js');
to
var socket = io.connect('http://localhost:80/');
I believe io.sockets.socket has been removed and has been a problem in Socket.IO (https://github.com/socketio/socket.io/issues/1618).
You can use io.sockets.connected[socket.id] and store the socket.id to reference with the user via username:
var usernames = {};
usernames[username] = socket.id;
// Sending the message
io.sockets.connected[usernames[username]].emit(...);
I don't see it anywhere on the documentation so I can see how this hasn't been answered. Also, if you don't have any reference via usernames, you can instead try:
users[socket.id] = socket.id;
to duplicate the key and value for easy access.
There is also possibly another way by using io.clients as described below, but I haven't used that method.
OTHER SOLUTION: Send message to specific client with socket.io and node.js
Have you tried using?
var socket = io.connect('http://localhost:80/');
i tired with the latest version of node and socket.io
below i am going to post complete code
<ul id="messages"></ul>
<form action="">
<input id="id1" /><button>Send</button>
</form>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var io = io.connect();
$('form').submit(function(){
io.emit('drumevent', $('#id1').val());
$('#id1').val('');
return false;
});
io.on('drumevent', function(msg){
console.log(msg);
$('#messages').append($('<li></li>').text(msg.message+' quantity = '+msg.quantity));
});
</script>
server side code
var usernames = {};io.on('connection', function(socket){usernames["username"] = socket.id;
socket.on('drumevent', function(msg){
var socketId = socket.id;io.to(socketId).emit('drumevent', data);

How to handle multiple chat sessions with Node.js

I am currently developing a chat system using Node.js. My question is, how do I handle multiple chat sessions with Node.js. That's a bit vague so I'll explain...
So for example two people might engage in a chat session. Node.js checks every couple of seconds for new messages. This is simple enough as I can get this to work fine using my code below.
My issue is when another two people at the same time are in another chat session.
At present I am sending two query strings called "chat_id" and "check_date" so it can check for new chat messages after a certain date and time.
Problem is, the "chat_id" and "check_date" are overwritten every time a new chat is started because the server is being used by both chat rooms.
Am I making sense?
My code below:
var chat_id, check_date;
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs"),
events = require("events");
// Conntect to database
var Client = require('mysql').Client;
var client = new Client();
client.host = 'localhost';
client.port = 3306;
client.database = '****';
client.user = '****';
client.password = '****';
client.connect(function(error, results) {
if(error) {
console.log('Connection Error: ' + error.message);
return;
}
console.log('Connected to MySQL');
});
// Check for chat updates
function getChatUpdates() {
if (typeof(check_date) == 'undefined')
return;
client.query('SELECT name, message FROM chat WHERE chat_id = "' + chat_id + '" AND date_entered > "' + check_date + '"',
function selectCb(error, results, fields) {
if (error) {
console.log('GetData Error: ' + error.message);
client.end();
return;
}
if (results.length > 0) {
for(var i = 0;i<results.length;i++) {
console.log('Name: ' + results[i]['name']);
console.log('Message: ' + results[i]['message']);
}
}
});
}
// Set interval to check for chat updates every 2 seconds
setInterval(getChatUpdates, 2000);
http.createServer(function(request, response) {
// Get the query strings
var uri = url.parse(request.url, true);
chat_id = uri.query.chat_id;
check_date = uri.query.check_date;
console.log('Chat ID: ' + chat_id);
console.log('Last Check: ' + check_date);
// we'll do something here later.
}).listen(8080);
sys.puts("Server running at http://localhost:8080/");
It seems like you are having a PHP background and when programming in node.js you should have a completely different mindset. You should not poll(setInterval(getChatUpdates, 2000);
) for messages, but push(callbacks/events) messages to users on event. I advice you to have a look at socket.io and use a in-memory database like redis(instead of mysql) to store your messages. When you code like this your site will perform much better and is going to be real-time(more). Also I would advice you to use express as your framework to develop websites instead of using raw http module. I don't know if you already know about npm, but you should use that to manage your dependencies.
var chat_id, check_date;
Are global variables. You are going to be overriding the chat_id on every connection (in createServer. You probably need some sort of session storage (to associate a user and their chat) eg. an Array, Redis, etc.
It looks like you trying to use MySQL as message queue. RabbitMQ?

Resources