Nodejs: Data exchange between Server and Client - node.js

I'm developing a server app in Node.js. For better understanding I wrote a very light code just to better point my issue. This is the server-side:
Server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 80;
var room = function(){
this.users = {};
this.counter = 0;
}
app.get('/reg',function(req,res){
console.log(req.params);
});
app.use('/recosh', express.static(__dirname + '/public/'));
app.listen(port, function(){console.log('ReCoSh Server Starts...\n');});
So inside the "public" directory I wrote the two following client-side files:
room.js
var room = {
//notifica al server una nuova registrazione
register: function(data){
$.getJSON('/reg',data);
}
}
index.html
<!doctype html>
<html>
<head>
<script src="room.js"></script>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script>
var register = function() {
room.register({
"username": $("#username").val(),
});
}
</script>
</head>
<body>
<div id="step1">
<input id="username">
<button onclick="register()">register</button>
</div>
</body>
</html>
The problem is that by inserting an username and clicking on register, the code console.log(req.params); on the server just print {}. It seems the object is empty... If I try console.log(req.params["username"]) it prints undefined.
Why this simple object is not visible by the server?

First of all you should change a little typo in your code into this
room.prototype.addUser = function(username){
if(username){
this.users[username] = username;
this.counter++;
}
}
changing this.user[username] to this.users[username]
Then change app.use('/register'.. to app.get('/register'.., but I would recommend to use post method, but let's make work with little modifications and besides this you don't call the register function inside the callback. So you should do something like this:
app.get('/register',function(req,res){
var data = {
username: req.params['username']
}
room.addUser(data.username);
console.log('user added\n');
});
On the other hand in your client side the input id is equal to nickname whereas you get the value by username id, so you should make this change as well:
<input id="nickname"> to <input id="username">

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

MongoDB saving one correct one wrong

This is my first project with these technologies and English is not my native language forgive me for all mistakes.
I am making Real-time Arduino NodeJS MongoDB project. My main goal is getting humidity, temperature and gas values from arduino. Storing them in Mongodb and publish these values on web site (localhost for now). Here is my NodeJS file. Couple variables are Turkish but its not that important i assume.
// Express bir server kurduk
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 8000;
// 8000. Porttan bağlantıyı sağlıyoruz
// mongoose kullandığımız veri tabanı kısmımız
var mongoose = require('mongoose');
var promise = mongoose.connect('mongodb://localhost/deneme2', {
useMongoClient: true,
});
promise.then(function(db) {
console.log('database e baglanildi')
});
// mongoose şeması tanımlaması
var Schema = mongoose.Schema;
var Veri = new Schema({
nem: String,
sicaklik: String,
sicaklik2: String,
sicaklik3: String,
gas: String,
body: String,
date: { type: Date,default: Date.now }});
var Veriler = mongoose.model('veri', Veri);
// server dinleniyor fonksiyonu
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
// yönlendirme
app.use(express.static(__dirname + '/public'));
var SerialPort = require("serialport").SerialPort
var serialPort = new SerialPort("/dev/ttyACM0", { //Arduino bağlantısını sağladığımız USB portumuz
autoOpen: false,
parser: SerialPort.parsers.readline('\r\n'),
baudrate:115200 // bitrate'imiz
});
//serialporttan okuyan ve datayı ekranımıza yazan fonksiyon
serialPort.open(function () {
console.log('NodeJS Arduino Projemiz Hazır');
serialPort.on('data', function(data) {
console.log(data);
io.sockets.emit('message', data.toString());
var test=data.toString();
var temp=test.split(",");
var veritabani=new Veriler({
nem: temp[0],
sicaklik: temp[1],
sicaklik2: temp[2],
sicaklik3: temp[3],
gas: temp[4]
});
veritabani.save(function(err){
if(err) throw err
});
});
});
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
});
Everything is fine. I am getting my data from Arduino like this way 31.0,24.0,297.0,185
I am saving it to the database but this is the first object which is wrong
{
"_id" : ObjectId("5a5285dd36e0c007967c3f66"),
"nem" : "",
"date" : ISODate("2018-01-07T20:41:01.168Z"),
"__v" : 0
}
And this is the second object which is correct.
{
"_id" : ObjectId("5a5285dd36e0c007967c3f67"),
"nem" : "32.0",
"sicaklik" : "24.0",
"sicaklik2" : "297.0",
"sicaklik3" : "56.0",
"gas" : "228",
"date" : ISODate("2018-01-07T20:41:01.193Z"),
"__v" : 0
}
It goes on and on againg like this one correct one wrong. I am using 800ms delay but i am going to try to change delay. I have no idea what is the problem. Also my html file :
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Ev Otomasyonu</title>
<script src="/socket.io/socket.io.js"></script>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script>
var socket = io.connect('http://localhost');
socket.on('message',function(data){
test=data.toString();
temp=test.split(',');
$('#nem').temp[0];
$('#sicaklik').text(temp[1]);
$('#sicaklik2').text(temp[2]);
$('#sicaklik3').text(temp[3]);
$('#gas').text(temp[4]);
});
</script>
</head>
<body>
<div>
<h1>Nem</h1>
<h1 id='nem'></h1>
</div>
<div>
<h1>Celcius</h1>
<h1 id='sicaklik'></h1>
</div>
<div>
<h1>Fahrenheit</h1>
<h1 id='sicaklik2'></h1>
</div>
<div>
<h1>Kelvin</h1>
<h1 id='sicaklik3'></h1>
</div>
<div>
<h1>Gaz</h1>
<h1 id='gas'></h1>
</div>
</body>
</html>
Which does not give me my values just writing the headers. I assume its because the first object in database that saved before.
According to the sample code in serialport package, you are listening with the 'flowing mode' which can introduce such behaviour. Have you try using the non flowing mode?
see sample code:
// Switches the port into "flowing mode"
port.on('data', function (data) {
console.log('Data:', data);
});
// Read data that is available but keep the stream from entering "flowing mode"
port.on('readable', function () {
console.log('Data:', port.read());
});

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) {...});

NowJs server different to web server

I'm playing around with nodejs and specifically looking at nowjs
I've got now up and running on a server running node and I have a separate web server. I successfully have the node server returning the client script and I reference this on the web server. This returns a 200 response code and all looks well. However I get javascript errors telling me that 'now' is undefined. As far as I understand it the 'now' variable should be available via the client script but this doesn't seem to be the case. Does anyone know if this set-up is possible? So the set-up is similar to the below pseudo code
//Server 1 node.com
if(request.url === '/nowjs/now.js'){
var file = 'path_to_clientlib/now.js';
fs.readFile(file, function(e, data) {
if (e) {
throw e;
}
response.writeHead(200,{'Content-Type': 'application/javascript'});
response.end(data);
}
and server.com
<script src="/jquery.js"></script>
<script src="http://node.com/nowjs/now.js"></script> <!-- This is returned properly -->
<script>
$(document).ready(function(){
now.receiveMessage = function(name, message){
$("#messages").append("<br>" + name + ": " + message);
}
$("#send-button").click(function(){
now.distributeMessage($("#text-input").val());
$("#text-input").val("");
});
now.name = prompt("What's your name?", "");
});
</script>
<div id="messages"></div>
<input type="text" id="text-input">
<input type="button" value="Send" id="send-button">
Straight away the console just returns 'now' is not defined
First of all there are enough modules that provide static file serving support, but if you want to manually serve a file I would do it like this...
var mime = require('mime') // Get mime type based on file extension. use "npm install mime"
, util = require('util')
, fs = require('fs');
function serveFile(filename, res) {
var filePath = process.cwd() + filename;
var stat = fs.statSync(filePath);
res.writeHead(200, {
'Content-Type':mime.lookup(filePath),
'Content-Length':stat.size
});
var readStream = fs.createReadStream(filePath);
return util.pump(readStream, res);
}
// Your code...
Or check out the module node-static on NPM or Github
About how to use NowJS (from the docs)
On the server
var httpServer = require('http').createServer(function(req, response){
// See code above how to serve static files...
});
httpServer.listen(8080);
var nowjs = require("now");
var everyone = nowjs.initialize(httpServer);
everyone.now.logStuff = function(msg){
console.log(msg);
}
On the client
<script type="text/javascript" src="http://localhost:8080/nowjs/now.js"></script>
<script type="text/javascript">
now.ready(function(){
// "Hello World!" will print on server
now.logStuff("Hello World!");
});
</script>

How to use Express post request to emit Socket.io or Sockjs?

I know this question is kind of awkward, but the problem comes from Samsung TV 2010 / 2011 SmartTV (and blue ray player; of course 2012 emulator working fine). I ported the simple chatting examples come from the source and package to SmartTV app. Both of them fall back to JSONP polling, but from SmartTV app only could emit / push to server once. Receiving the message from server could be multiple times without any problem. After looking for the answer in Samsung D forum (of course nothing there), I think the fastest way to work around this issue is to deploy an Express server, taking the post data and JSON.parse, then emit Socket.io / Sockjs internally inside the server itself.
Could anybody show me an easy sample code so I could start from there? Thanks a lot.
I quickly make code, but seems it doesn't work:
lib/server.js
var express = require('express')
, app = express.createServer()
, io = require('socket.io').listen(app);
app.listen(80);
app.use(express.bodyParser());
app.get('/', function (req, res) {
res.sendfile('/var/www/mpgs_lite_v3/index.html');
});
app.post('/', function(req, res){
console.log(req.body);
io.sockets.emit('my other event', req.body);
res.redirect('back');
});
io.sockets.on('connection', function (socket) {
//socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
index.html
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
</head>
<body>
<form method="post" action="/">
<input type="hidden" name="_method" value="put" />
<input type="text" name="user[name]" />
<input type="text" name="user[email]" />
<input type="submit" value="Submit" />
</form>
</body>
</html>
'my other event' seems not receive anything.
UPDATE: I updated the example for you to make it more complete. I didn't have an app.listen before, and here is also a client side script which shows that it, indeed, works fine:
<!doctype html>
<html>
<head>
<script src="//www.google.com/jsapi"></script>
<script src="/socket.io/socket.io.js"></script>
<script>google.load("jquery", "1.7.1")</script>
<script>
var socket = io.connect("localhost", {port: 3000});
socket.on("foo", function(message) { console.log("foo: ", message) });
$(function() {
$("button").click(function() {
$.post("/foo", { message: $("input").val() });
});
});
</script>
</head>
<body>
<input type=text>A message</input>
<button>Click me!</button>
</body>
</html>
And the server, now with an app.listen directive:
var express = require("express"),
app = express.createServer(),
io = require("socket.io").listen(app)
index = require("fs").readFileSync(__dirname + "/index.html", "utf8");
app.use(express.bodyParser());
app.get("/", function(req, res, next) {
res.send(index);
});
app.post("/foo", function(req, res, next) {
io.sockets.emit("foo", req.body);
res.send({});
});
app.listen(3000);
Usage:
node app.js
Navigate to http://localhost:3000/ and click the button. Check your console for output.
Based on SockJS express example server.js could look like:
var express = require('express');
var sockjs = require('sockjs');
// 1. Echo sockjs server
var sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.2.min.js"};
var sockjs_echo = sockjs.createServer(sockjs_opts);
connections = {};
sockjs_echo.on('connection', function(conn) {
console.log(conn.id);
connections[conn.id] = conn
conn.on('close', function() {
delete connections[conn.id];
});
// Echo.
conn.on('data', function(message) {
conn.write(message);
});
});
// 2. Express server
var app = express.createServer();
sockjs_echo.installHandlers(app, {prefix:'/echo'});
console.log(' [*] Listening on 0.0.0.0:9999' );
app.listen(9999, '0.0.0.0');
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.post("/send", function(req, res, next) {
for(var id in connections) {
connections[id].write('received POST');
}
res.send({});
});
To test open browser at localhost:9999 and run:
curl localhost:9999/send -X POST
just remove this comment
//socket.emit('news', { hello: 'world' });
to
socket.emit('news', { hello: 'world' });
it will work because its emiting data through news and you are listening using my other event instead of 'news' or you can do just listen using 'my other event'
I don't know if this would help, but you can make an emit abstraction on the client based on your browser and then make a separate get function on the server that will handle the request the same way as the socket.on callback. In order to know where to send the information I suggest you use some key that you can store in a hash table in the server and local storage on the client.
For the client:
var emit = function(event, options) {
if ("WebSocket" in window) {
socket.emit(event, options);
console.log("emited via WebSocket");
} else {
$.post("http://localhost/emit/" + event, options);
console.log("emited via AJAX");
}
}
emit("echo", {
key: localStorage.getItem("key"),
data: {
hello: "world"
}
});
socket.on("response", function(data) {
console.log(data.hello); //will print "world"
});
For the server:
var sockets = {};
var echo_handler = function(a) {
var socket = sockets[a.key];
var data = a.data;
socket.emit("response", data);
}
app.post("/emit/:event", function(req, res) {
var event = req.params.event;
switch (event) {
case "echo":
var a = {
key: req.param("key"),
data: req.param("data")
}
echo_handler(a);
break;
}
});
io.sockets.on("connection", function(socket) {
socket.on("connect", function(data) {
sockets[data.key] = socket;
});
socket.on("echo", echo_handler);
});
Another way to do this will be to switch to Sockjs and use their patch.
If someone have better solution for Socket.IO it will be appreciated, because I'm already deep into the project and it's too late to switch Socket.IO for Sockjs, and this solution is not to my liking :( .

Resources