Web application using websockets and node.js - html

I'm new to HTML5 and node.js. I'm trying to create a very basic client-server application. Here is the code.
Server side (node.js):
var net = require('net');
var server = net.createServer(function(c) {
console.log('client connected');
c.setEncoding('utf8');
c.on('end', function() {
console.log('client disconnected');
});
c.on('data', function(data) {
console.log(data);
c.write("Got it");
});
});
server.listen(9998);
Client side (websockets):
<!DOCTYPE html>
<html>
<head>
<script>
try {
var ws = new WebSocket('ws://127.0.0.1:9998');
ws.onopen = function() {
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt) {
var message = evt.data;
alert("Message is received: " + message);
};
ws.onclose = function() {
alert("Connection is closed...");
};
} catch (err) {
alert(err.message);
}
</script>
</head>
<body>
</body>
</html>
As far as I understand, the client should connect to the server, send "Message to send" and the server should reply with "Got it". Instead what the server receives is an http GET request for the client html page and none of the client callbacks are ever fired. What am I missing?

You are missing the very point of WebSocket, its TCP but not raw TCP, to establish a connection the client must send an HTTP request first, then the servers switches protocols to websockets, but remember websocket is not raw TCP, there are custom headers in packets and other.
To save your self some time, try https://github.com/LearnBoost/Socket.IO/ or other websocket libraries https://github.com/joyent/node/wiki/Modules.

Related

Reading Arduino data using WebSocket with HTML & nodejs

I can't quite grasp the last step in this puzzle. Everything compiles, and it is "bug-free". This is my first foray into communications/full-stack and I have been stumped despite numerous excellent tutorials.
[WORKING] Arduino reads and interprets sensor data
[WORKING] index.js acquires data with serial communication over USB
[WORKING] index.js creates a WebSocket connection using nodejs
[WORKING] index.html performs the WebSocket handshake
[WORKING] index.html uses Plotly to create a real-time line graph
[WIP] index.html passes through the Arduino data in the Plotly function
Chopped down index.html:
<script src="server/plotly.min.js"></script>
<script>
//connection to the web socket server
const ws = new WebSocket("ws://localhost:5000");
let foo = 0.0;
//working
ws.addEventListener("open", () => {
console.log("We Are Connected");
ws.send("TestData");
});
//working
ws.addEventListener("message", e => {
console.log(e);
console.log("Data Recieved! Success.");
});
</script>
Rest of the file is just the graphing function which I would like to pass through Arduino data.
index.js
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 5000 });
//create a serial port that allows serial connection from Arduino
let SerialPort = require("serialport");
let port = new SerialPort('COM4', { baudRate: 9600 });
let Readline = require("#serialport/parser-readline");
let parser = port.pipe(new Readline({ delimiter: '\n' }));
wss.on("connection", ws => {
//working
console.log("New Client Connection");
//this is what I need to passthrough my Plotly arg
parser.on("data", data => {
//event is firing but can't get client to grab this. Console logs data correctly.
console.log(RPM: ${data});
});
//working on both ends
ws.on("message", data => {
console.log("TEST")
ws.send(data);
});
//doesn't log?
port.on("open", () => {
console.log("Serial Port Open");
});
});
//working
console.log("The server is ON");
I'm looking for a strategy or method to grab the sensor data in my HTML file. Is it something simple conceptually I am missing? Thank you.
You established a websocket server, and it is works. If you want to send message to websocket, define a socket to the websocket server, get out the Serial part from websocket server, and run is standalone, and send data from this to the websocket.
Like this:
const http = require('http');
const WebSocketServer = require('websocket').server;
const server = http.createServer();
server.listen(5000);
const wsServer = new WebSocketServer({
httpServer: server
});
let SerialPort = require("serialport");
var serialPort = new SerialPort("COM5", {
baudRate: 9600,
parser: new SerialPort.parsers.Readline("\n")
});
var connection;
wsServer.on('request', function(request) {
connection = request.accept(null, request.origin);
connection.on('message', function(message) {
console.log('Received Message:', message.utf8Data);
connection.sendUTF('Hi this is WebSocket server!');
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
serialPort.on('open',function(){
//connection.sendUTF('Hi this is WebSocket server!');
console.log('open');
serialPort.on('data', function(data){
readData = data.toString();
console.log("N<", readData);
if( typeof connection!="undefined")
connection.sendUTF( readData);
});
});

Send data to server using socket.io with Node.js

in simple form i use:
onsubmit="return sendMessage()" action="/register"
to send data with socket.io to server:
function sendMessage() {
var name = document.getElementById("Name").value;
socket.emit('new_rgs', {
'name': name,
});
return false;
}
and i want to save result to text file too,
i use express.js to do this:
app.post('/register', urlencodedParser, (req, res) => {
var info = {};
info["name"] = req.body.Name;
fs.appendFileSync("register.json", JSON.stringify(info));
res.render('pages/register', {
"send": 1
});
});
but post method doesn't send anything :(
if you want check all codes it's here
You need to do a separate call to the /register route. What your current code does is that it only does an emit to the socket. You need a separate AJAX call towards the register route.

How to get sensor data over TCP/IP in nodejs?

I have a nodejs app with socket.io. To test this, save the below listing as app.js. Install node, then npm install socket.io and finally run on command prompt: node app.js
var http = require('http'),
fs = require('fs'),
// NEVER use a Sync function except at start-up!
index = fs.readFileSync(__dirname + '/index.html');
// Send index.html to all requests
var app = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(index);
});
// Socket.io server listens to our app
var io = require('socket.io').listen(app);
// Send current time to all connected clients
function sendTime() {
io.sockets.emit('time', { time: new Date().toJSON() });
}
// Send current time every 10 secs
setInterval(sendTime, 5000);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', { message: 'Welcome!' });
socket.on('i am client', console.log);
});
app.listen(3000);
This code sends data to the file index.html. After running the app.js, open this file in your browser.
<!doctype html>
<html>
<head>
<script src='http://code.jquery.com/jquery-1.7.2.min.js'></script>
<script src='http://localhost:3000/socket.io/socket.io.js'></script>
<script>
var socket = io.connect('//localhost:3000');
socket.on('welcome', function(data) {
$('#messages').html(data.message);
socket.emit('i am client', {data: 'foo!'});
});
socket.on('time', function(data) {
console.log(data);
$('#messages').html(data.time);
});
socket.on('error', function() { console.error(arguments) });
socket.on('message', function() { console.log(arguments) });
</script>
</head>
<body>
<p id='messages'></p>
</body>
</html>
The data sent right now is the current time and index.html works fine, updates the time every five seconds.
I want to modify the code so that, it reads my sensor data over TCP. My sensors are connected thru a data acquisition system and relays the sensor data over IP: 172.16.103.32 port:7700. (This is over LAN, so will not the accessible to you.)
How can this be implemented in nodejs?
Is SensorMonkey a viable alternative ? If so, any pointers on how to go about using it?
I have a decent hack that is working right now, for which I request the readers to comment on....
var net = require('net'),
http = require('http'),
port = 7700, // Datalogger port
host = '172.16.103.32', // Datalogger IP address
fs = require('fs'),
// NEVER use a Sync function except at start-up!
index = fs.readFileSync(__dirname + '/index.html');
// Send index.html to all requests
var app = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(index);
});
// Socket.io server listens to our app
var io = require('socket.io').listen(app);
// Emit welcome message on connection
io.sockets.on('connection', function(socket) {
socket.emit('welcome', { message: 'Welcome!' });
socket.on('i am client', console.log);
});
//Create a TCP socket to read data from datalogger
var socket = net.createConnection(port, host);
socket.on('error', function(error) {
console.log("Error Connecting");
});
socket.on('connect', function(connect) {
console.log('connection established');
socket.setEncoding('ascii');
});
socket.on('data', function(data) {
console.log('DATA ' + socket.remoteAddress + ': ' + data);
io.sockets.emit('livedata', { livedata: data }); //This is where data is being sent to html file
});
socket.on('end', function() {
console.log('socket closing...');
});
app.listen(3000);
References:
Socket.io Website - www.socket.io - Its the buzzword now.
TCP Socket Programming
Nodejs "net" module
Simplest possible socket.io example.

Server sent event: Client not receiving response from server

I'm trying to use server sent events so my webpage can have periodic time updates from my server. The issue is that my client is able to interact with my server, however, the response from my server is not making it to my client? Basically, when I open my html file with firefox I know my server gets the request and then it starts sending responses, but nothing shows up on my webpage... Not quite sure what's the issue. Help appreciated!
Here is my client code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<script>
function init(){
if(typeof(EventSource)!=="undefined"){
var source = new EventSource('localhost');
source.onmessage = function(e) {
document.body.innerHTML += e.data + '<br>';
};
}
else{
document.body.innerHTML = "Sorry, your browser does not support server-sent events...";
}
}
</script>
<body onload="init()">
</body>
</html>
Here is my server code (node.js):
var http = require('http');
var sys = require('sys');
var fs = require('fs');
http.createServer(function(req, res) {
if (req.headers.accept && req.headers.accept == 'text/event-stream') {
sendSSE(req, res);
}).listen(80, "127.0.0.1");
function sendSSE(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
var id = (new Date()).toLocaleTimeString();
// Sends a SSE every 5 seconds on a single connection.
setInterval(function() {
constructSSE(res, id, (new Date()).toLocaleTimeString());
}, 5000);
}
function constructSSE(res, id, data) {
res.write('id: ' + id + '\n');
res.write("data: " + data + '\n\n');
}
You need to add in
res.end();
somewhere and remove the 'setInterval'. It looks like what you're trying to do, however, is keep the connection alive, in which case you need to change your code significantly. Look into the 'net' module, which is more designed for a "constant on" interactive type of connection.
http://nodejs.org/api/net.html#net_net
The http module is designed for finite, exchange of data, type of requests. You're trying to make it do something it isn't designed to do.
/*jshint node:true */
var http = require('http');
http.createServer(function (req, res) {
'use strict';
console.log('GOOD request recieved');
res.write('hi there');
res.end();
console.log('GOOD end sent');
}).listen(8888);
http.createServer(function (req, res) {
'use strict';
console.log('BAD request received');
res.write('hi there');
console.log('BAD response wrote not ending');
}).listen(8889);
Consider the two servers I have above. If you ping them both with node client code, you will see data come in to both, and should see chunks as they are sent. However, if you try to ping 8889 with a browser, the webpage will never render, because the end event is never sent. Browsers depend on this to know all content has been received. If you're client code is working within a browswer, this may be effecting things. Attempt to use plain NodeJS client code against your server first, and make sure data is getting sent the way you expect it is. Then work on figuring out how the browser is upsetting things. My guess would be that the data gets received by the browser, but it never does anything with it, and sits and waits to distribute it for that 'end' event, the same way in which the 8889 server's webpage never renders... it believes there is more data to wait for.
Sample client code:
var options = {
hostname: '127.0.0.1',
method: 'GET'
};
options.port = 8888;
http.request(options, function (res) {
'use strict';
console.log('GOOD Pinged server');
res.on('data', function (chunk) {
console.log('GOOD data chunk:' + chunk);
});
res.on('end', function () {
console.log('GOOD end event recieved');
});
}).end();
options.port = 8889;
http.request(options, function (res) {
'use strict';
console.log('BAD Pinged server');
res.on('data', function (chunk) {
console.log('BAD data chunk:' + chunk);
});
res.on('end', function () {
console.log('BAD end event recieved');
});
}).end();
The http module in node works fine for Server Sent Events and most demo code for Node SSE uses it. But you do have to be careful about some gotchas.
I got bit by compression being turned on. The solution there is to add res.flush() after the last res.write() of each data message. Since that's an easy fix, I would try that first before rewriting using a different module.

how to get session from codeigniter with node.js

i'm writing application like social network where in my application can show status update and chat . when i search on internet i found node.js for long polling technology and i think i can use that for chat and streaming page in my application. but when i use node.js i have a stack
this is a technology i want to my project:
1) i'm using codeigniter for framework and mysql database in address localhost:81/myproject
2) and using node.js in port 127.0.0.1:8080 to chat and streaming page
this is code javascript server with node.js name is server.js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs"),
events = require("events");
function load_static_file(uri, response) {
var filename = path.join(process.cwd(), uri);
path.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Found\n");
response.end();
return;
}
fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.end();
return;
}
response.writeHead(200);
response.write(file, "binary");
response.end();
});
});
}
var local_client = http.createClient(81, "localhost");
var local_emitter = new events.EventEmitter();
function get_users() {
var request = local_client.request("GET", "/myproject/getUser", {"host": "localhost"});
request.addListener("response", function(response) {
var body = "";
response.addListener("data", function(data) {
body += data;
});
response.addListener("end", function() {
var users = JSON.parse(body);
if(users.length > 0) {
local_emitter.emit("users", users);
}
});
});
request.end();
}
setInterval(get_users, 5000);
http.createServer(function(request, response) {
var uri = url.parse(request.url).pathname;
if(uri === "/stream") {
var listener = local_emitter.addListener("users", function(users) {
response.writeHead(200, { "Content-Type" : "text/plain" });
response.write(JSON.stringify(users));
response.end();
clearTimeout(timeout);
});
var timeout = setTimeout(function() {
response.writeHead(200, { "Content-Type" : "text/plain" });
response.write(JSON.stringify([]));
response.end();
local_emitter.removeListener(listener);
}, 10000);
}
else {
load_static_file(uri, response);
}
}).listen(8383);
sys.puts("Server running at http://localhost:8383/");
now in codeigniter side i making webservices on url http://localhost:81/myproject/getUser with response is json format and i access this with session auhtentication if not is redirect to login page.
[{"user_id":"2a20f5b923ffaea7927303449b8e76daee7b9b771316488679","token":"3m5biVJMjkCNDk79pGSo","username":"rakhacs","password":"*******","name_first":"rakha","name_middle":"","name_last":"cs","email_id":"email#gmail.com","picture":"img\/default.png","active":"1","online":"0","created_at":"2011-09-20 11:14:43","access":"2","identifier":"ae70c3b56df19a303a7693cdc265f743af5b0a6e"},{"user_id":"9a6e55977e906873830018d95c31d2bf664c2f211316493932","token":"RoUvvPyVt7bGaFhiMVmj","username":"ferdian","password":"*****","name_first":"willy","name_middle":"","name_last":";f;w","email_id":"email1#gmail.com","picture":"img\/default.png","active":"1","online":"0","created_at":"2011-09-20 11:47:20","access":"2","identifier":"1ccd4193fa6b56b96b3889e59c5205cc531177c9"}]
this is the point problem when i execute node server.js
i get error like this undefined:0
sysntaxerror:unexpected end of input
at object.parse(native)
i don't know about that error i think because i using session ? but i'm not sure.
when i test using test.js for testing my webservices
var http = require("http")
var options = {
host: 'localhost',
port: 81,
path: '/myproject/getUser',
method: 'GET'
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
and this is the output
problem with request: parse error
but when i using another webservice who has been response json format too and not using session that's work i can get the body response..if this problem is session how i can fix this?..this is can make me confused..thanks for your comment
hard to say but I would primary try to send an object in jSON and not directly an array. i.e. just encapsulate the array into an object:
{"data":[…]}
This "may" be causing the parse error.
Something else, for this purpose, it won't be bad to add the following to your responding PHP method:
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Content-type: application/json');