When opening multiple clients, old client does not get updated using nodejs web socket - html

My goal is when I open a new browser(client), the message sent from the server in the previous client gets updated as well.
Currently,
The clients send messages to the server, the server stores them in localStorage as an array and should send it back to all the clients. All clients should get the same array of messages. It works like ajax call.
As of right now, when I open the first browser, the message is sent to the server and received in the client successfully, and then I open the second one(it works) but the message is not updated in the first browser. PS this acts like a forum, when somebody posts a messages to server, all users should be able to see it.
Here's my code for server:
<html>
<head>
<!-- This is the websocket SERVER -->
<script src="http://localhost:5000/socket.io/socket.io.js"></script>
</head>
<body>
<div id="msg"></div>
<script>
// connect to WEBSOCKET server
var socket = io.connect('http://localhost:5000',{'forceNew':true} );
// Fire an event (that the server will handle
socket.emit('myEvent', 'Hello Message from the client');
// Attach event handler for event fired by server
socket.on('server', function(data) {
var elem = document.getElementById('msg');
console.log(data);
elem.innerHTML += "<br>" + data; // append data that we got back
});
</script>
</body>
</html>
Here's for client:
//---------------------------------------------------------------
// The purpose is to introduce you to websockets
// This is a SERVER that is SEPARATE from the http server.
//
// Your webpage (in this case the index.html in this directory)
// will be SERVED by the http server. THEN, it will connect to the
// websocket server. Then - they will talk to each other!
//
// Note that in regular http - the server cannot initiate a conversation
// Here, the websocket server sends a message to the client browser.
//
// This example has THREE parts
// 1) The http server code (which is same as what we did earlier)
// 2) This code - this is the web socket server
// It prints what it got from client. It also sends a message to the
// client after every 1 second.
// 3) The html or client code. Note how it connects to the websocket
// and how it sends and receives messages
//
// To RUN THIS EXAMPLE
// First, run node httpServer.js on one terminal
// Next, run node 1_ws.js on another terminal
// Next, type localhost:4000/index.html on some browser
//
//---------------------------------------------------------------
var items=[];
var io = require('socket.io').listen(5000);
if (typeof localStorage === "undefined" || localStorage === null) {
var LocalStorage = require('node-localstorage').LocalStorage;
localStorage = new LocalStorage('./scratch');
}
io.sockets.on('connection', function(socket) {
socket.on('myEvent', function(content) {
//i need to store the content
items.push(content);
localStorage.setItem("list",JSON.stringify(items));
socket.emit('server', JSON.parse(localStorage.getItem("list")));
});
});
I'm running on the local server:( you can ignore the local server if you want, the above code can function on their own)
//---------------------------------------------------------------
// The purpose is to serve a file!
//---------------------------------------------------------------
var util = require('util');
var path = require('path');
var http = require('http');
var fs = require('fs');
var server = http.createServer();
// attach handler
server.on('request', function (req,res) {
var file = path.normalize('.' + req.url);
fs.exists(file, function(exists) {
if (exists) {
var rs = fs.createReadStream(file);
rs.on('error', function() {
res.writeHead(500); // error status
res.end('Internal Server Error');
});
res.writeHead(200); // ok status
// PIPE the read stream with the RESPONSE stream
rs.pipe(res);
}
else {
res.writeHead(404); // error status
res.end('NOT FOUND');
}
});
}); // end server on handler
server.listen(4000);
console.log("start");

You are sending response to only client who sent message to sever only,
To send to all clients which are connected you must use this,
io.emit('server', JSON.parse(localStorage.getItem("list")));
Visit this answer for all
Responses

Related

Real-time database view on HTML page with Socket.io

I have a raspberry Pi that is constantly pushing data to a MySQL database via PHP. I am trying to create a website where I can see the contents of this database realtime.
I've been following this tutorial : http://markshust.com/2013/11/07/creating-nodejs-server-client-socket-io-mysql which shows an example on using socket.io for this purpose. This is working fine from 2 clients, when I add a new note it updates on both browsers. The problem is when I manually add a record to the database from mysql CLI, it does not update. I'm guessing this is because there is no emit happening. How can I implement this?
Server.js:
var mysql = require('mysql')
// Let’s make node/socketio listen on port 3000
var io = require('socket.io').listen(3000)
// Define our db creds
var db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'node'
})
// Log any errors connected to the db
db.connect(function(err){
if (err) console.log(err)
})
// Define/initialize our global vars
var notes = []
var isInitNotes = false
var socketCount = 0
console.log("connected");
io.sockets.on('connection', function(socket){
// Socket has connected, increase socket count
socketCount++
// Let all sockets know how many are connected
io.sockets.emit('users connected', socketCount)
socket.on('disconnect', function() {
// Decrease the socket count on a disconnect, emit
socketCount--
io.sockets.emit('users connected', socketCount)
})
socket.on('new note', function(data){
// New note added, push to all sockets and insert into db
notes.push(data)
io.sockets.emit('new note', data)
// Use node's db injection format to filter incoming data
db.query('INSERT INTO notes (note) VALUES (?)', data.note)
})
// Check to see if initial query/notes are set
if (! isInitNotes) {
// Initial app start, run db query
db.query('SELECT * FROM notes')
.on('result', function(data){
// Push results onto the notes array
notes.push(data)
})
.on('end', function(){
// Only emit notes after query has been completed
socket.emit('initial notes', notes)
})
isInitNotes = true
} else {
// Initial notes already exist, send out
socket.emit('initial notes', notes)
}
})
Index.html:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script>
$(document).ready(function(){
// Connect to our node/websockets server
var socket = io.connect('http://localhost:3000');
// Initial set of notes, loop through and add to list
socket.on('initial notes', function(data){
var html = ''
for (var i = 0; i < data.length; i++){
// We store html as a var then add to DOM after for efficiency
html += '<li>' + data[i].note + '</li>'
}
$('#notes').html(html)
})
// New note emitted, add it to our list of current notes
socket.on('new note', function(data){
$('#notes').append('<li>' + data.note + '</li>')
})
// New socket connected, display new count on page
socket.on('users connected', function(data){
$('#usersConnected').html('Users connected: ' + data)
})
// Add a new (random) note, emit to server to let others know
$('#newNote').click(function(){
var newNote = 'This is a random ' + (Math.floor(Math.random() * 100) + 1) + ' note'
socket.emit('new note', {note: newNote})
})
})
</script>
<ul id="notes"></ul>
<div id="usersConnected"></div>
<div id="newNote">Create a new note</div>
This is similar to a previous question, where it appears there was no simple way to do this with MySQL.
If you are in an early enough stage of development that you are not tied to MySQL, then I will point out that you can solve this problem with postgresql:
Be pushed to from PHP via PDO library (see docs).
Runs on the Raspberry Pi.
Can detect updates pushed from anywhere on the command-line via pg_notify on a trigger (see docs).
Updates can be subscribed to with NodeJS via the pg package.
On a technical level this will work, but databases in general are not efficient as messaging systems (watch out for the Database-as-IPC anti-pattern). The PHP client could also emit its own notification when things happen, via a message queue, UDP socket, or something else.

How to send Data to the client with out client requesting the ws server in nodejs

I need to convert a csv file to json format and send it to a client requesting to ws server in nodejs ,
the file will be updated so many times so i need to send updated data to client
i am able to send data once it is loaded completely(like when app is started it sends all data in file to client) but when i update data in the file the updated data is being printed out on console but it is not being sent to client is their any thing wrong in my code
my node.js code:
var ts = require('tail-stream');
var Converter = require("csvtojson").Converter;
var converter = new Converter({constructResult:false}); //for big csv data
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets server
// we don't have to implement anything.
response.write('hello');
console.log('in http server \n');
});
server.listen(1337, function() { });
// create the server
wsServer = new WebSocketServer({
httpServer: server
});
// WebSocket server
wsServer.on('request', function(request) {
var connection = request.accept(null, request.origin);
console.log('wsserver');
connection.send('ws server');
converter.on("record_parsed", function (jsonObj) {
console.log(jsonObj); //here is your result json object
connection.send(jsonObj);
});
var tstream = ts.createReadStream('log.csv', {
beginAt: 0,
onMove: 'follow',
detectTruncate: false,
onTruncate: 'end',
endOnError: false
});
tstream.pipe(converter);
});
Right now you are creating a new read stream and adding a listener to the converter on every new connection, that will cause trouble once you have more than one client (same event emitted multiple times, etc..). Instead of that you should keep just one reader and notify all open connections when there's a new record.
Also notice that the library you are using only accepts UTF-8 strings or binary type messages, row objects sent the way you're sending them now will be received as a "[object Object]" string after toString() is called on them. You should probably send just send the row string or use JSON.stringify / JSON.parse.
Try this:
var http = require("http");
var tailStream = require("tail-stream");
var Converter = require("csvtojson").Converter;
var WebSocketServer = require("websocket").server;
var server = http.createServer();
var wsServer = new WebSocketServer({ httpServer: server });
var converter = new Converter({constructResult:false});
var logStream = tailStream.createReadStream("log.csv", { detectTruncate : false });
var connections = [];
server.listen(1337);
logStream.pipe(converter);
//----------------------------------------------------
converter.on("record_parsed", function (jsonObj) {
connections.forEach(function(connection){
connection.send(JSON.stringify(jsonObj));
});
});
//----------------------------------------------------
wsServer.on("request", function(request) {
var connection = request.accept(null, request.origin);
connection.on("close", function() {
connections.splice(connections.indexOf(connection), 1);
});
connections.push(connection);
});
The code above works, tested like this on the client side:
var socket = new WebSocket('ws://localhost:1337/');
socket.onmessage = function (event) {
console.log(JSON.parse(event.data));
}
Note: this doesn't send the whole content of the file at the beginning, just the updates, but you can easily achieve this storing the records and sending them on new connections.

Send a message from client to server

I have a server I wrote in NodeJs which listens to port 1234.
From my client (html) I want to send request to my server and wait for an answer.
I tried to use XMLHttpRequest:
var http = new XMLHttpRequest();
var url = "127.0.0.1:1234";
var params = "token=22";
http.open("post", url, true);//"https://www.google.com/search?q=asd"
http.setRequestHeader("Content-type", "text/html");
http.setRequestHeader("Content-length", 0);
http.setRequestHeader("Connection", "keep-alive");
http.onreadystatechange = function() {//Call a function when the state changes.
alert(http.responseText);
}
http.ontimeout = function()
{
alert("timeout");
}
http.timeout=10;
try
{
http.send(null);
}
catch(ex)
{
alert(ex);
}
But I always got exception. The reason was I can't use my own port.
Is There any other way to send request and get respond?
There is nothing wrong with using JQuery.ajax to make your life easier and it does get a lot easier with jquery especially when it comes to XMLHttpRequest.

multiple websockets connections on the same client - server cannot handle

Let me clarify, this is kind of complicated.
I'm implementing a form to insert data in the database.
I have two websockets connections in the same client side, connecting on the same nodejs server.
One connection is triggered after the user inserts a name on the "name" textfield of the form. Sends the data to the server, server checks the database if the name already exists and responces back "This already exists. Mayde you are inserting something that is already there".
The other connection is triggered if all the fields of the form are not blank and sends the data to server to insert them in the database.
I thought it was a good idea to distinguish on server-side ,the different connections using arrays. If the first element of the array is "name" call the checkName function, or if it is "insert" , call the insertInDB function.
I created two small testing files. They do not work. Connections are open and the client sends the data. I get no errors inte server nor the client side. But server never responces. I dont get the expected numbers, back in the client side. I dont think this is the right anyway. This is complecated, I hope the code helps you.
Is it possible, what I am trying to do? Any hints or alternatives?
Thanks
the code....
server-side
function WebSocketTest1(){
var a=1;
var b=2;
var c = [a,b];
var so = new WebSocket("ws://localhost:1337");
so.onerror=function (evt)
{message.textContent = evt;}
so.onopen = function(){
message.textContent = "opened";
so.send(c);
message.textContent = "sended";
}
so.onmessage = function (evt) {
var received_msg = evt.data;
document.getElementById("message").innerHTML=received_msg;
}
}
function WebSocketTest2(){
var d=3;
var e=4;
var f = [d,e];
var sa = new WebSocket("ws://localhost:1337");
sa.onerror=function (evt)
{message2.textContent = evt;}
sa.onopen = function(){
message2.textContent = "opened";
sa.send(f);
message2.textContent = "sended";
}
sa.onmessage = function (evt) {
var received_msg = evt.data;
document.getElementById("message2").innerHTML=received_msg;
}
}
</script>
</head>
<input type="button" value="one" onClick="WebSocketTest1()"><br/>
<input type="button" value="two" onClick="WebSocketTest2()"><br/>
<body>
<div id="message"></div>
mesage2</br>
<div id="message2"></div>
</body>
</html>
on the server side I am listing the sessions, to communicate only with a specific session, code found here
and the server side (snippets)
var connections = {};
var connectionIDCounter = 0;
var connection = request.accept(null, request.origin);
// Store a reference to the connection using an incrementing ID
connection.id = connectionIDCounter ++;
connections[connection.id] = connection;
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
var ja=message;
if(ja[0]==1)
{ja[1]=7;}
else if(ja[0]==3)
{ja[1]=8;}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
delete connections[connection.id];
});
});
// Send a message to a connection by its connectionID
function sendToConnectionId(connectionID, data) {
var connection = connections[connectionID];
if (connection && connection.connected) {
connection.send(ja[1]);
}
I wonder why you need 2 connections.
Open one connection and send the payload as JSON.
e.g.
var ws = new WebSocket("ws://localhost:1336");
ws.send(JSON.stringify({ command: "checkname", params: "xxxx"; });
ws.send(JSON.stringify({ command: "submit", params: { ... });
At the server side, you just have to parse the payload and determine which command is executed.
I am just wondering why you need websocket. It seems that you need to validate user presence in the application. If user is not present then you need to insert in the database else throw error.
you can go through jquery post and jquery form validation
http://api.jquery.com/jQuery.post/

Client side tcp with node.js/socket.io?

I'm new to node.js/socket.io so I don't really know what I'm doing, but I've got this for my server side:
var app = require('net')
, fs = require('fs')
var server = app.createServer(function (socket) {
socket.write("Echo server\r\n");
socket.pipe(socket);
socket.on('data', function(data) {
console.log(data);
});
});
var io = require('socket.io').listen(server)
server.listen(81);
So the tcp server works when I use nc localhost 81 and send it data. However, I don't know how to connect and send data to the tcp server on a website from the server side using script tags. So what would the client side be to connect to this tcp server and send data to it?
Thanks!
Newly added code:
Server:
var app = require('net')
, fs = require('fs')
var sockets_list = [];
var server = app.createServer(function (socket) {
sockets_list.push(socket);
socket.write("Echo server\r\n");
socket.on('data', function(data) {
console.log(data);
for (var i = 0; i < sockets_list.length; i++) {
sockets_list[i].write(data);
}
});
socket.on('end', function() {
var i = sockets_list.indexOf(socket);
sockets_list.splice(i, 1);
});
});
server.listen(81);
Client:
<script type="text/javascript" src="http://localhost:82/socket.io/socket.io.js"> </script>
<script>
var socket = io.connect('http://localhost:81');
socket.on('connect', function () {
socket.send('hi');
});
socket.send('hi1');
socket.emit('hi2');
alert('here');
</script>
What happened:
I have a webpage loading which takes one socket and a nc localhost 81 which takes up another socket. So the nc displays everything the web page sends. After I connect the webpage, the alert('here'); is executed and the nc shows the http request, however, nothing else is sent to the tcp server, and the webpage is in constant refresh status. Why does the webpage never fully load, the 'hi' messages never get sent, and what about the http request to a tcp server? Why doesn't my tcp client fail with my tcp server?
Socket.io's how to use page shows you exactly how to do that.
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost/');
socket.on('connect', function () {
socket.send('hi');
socket.on('message', function (msg) {
// my msg
});
});
</script>