I have deployed below code in OpenShift Cloud platform by Red-hat for NodeJs chat application, I am not getting any error in Console(F12) and response code as Ok 200..but the application is not working
Server(you can find complete source at https://github.com/varund29/openshift/blob/master/index.js)
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server, { origins:'http://nodejs-atnodejs.rhcloud.com:8000' });
app.get('/', function (req, res) {
res.sendfile('index.html');
});
io.on('connection', function (socket) {
socket.on('chatmessage', function (msg) {
console.log('index.js(socket.on)==' + msg);
io.emit('chatmessage', msg);
});
});
server.listen(process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP);
Client(you can find complete source at https://github.com/varund29/openshift/blob/master/index.html)
src="http://nodejs-atnodejs.rhcloud.com:8000/socket.io/socket.io.js
src="http://code.jquery.com/jquery-1.11.1.js"
var socket = io.connect('http://nodejs-atnodejs.rhcloud.com:8000');
$('button').click(function (e) {
console.log('index.html($(button).click)=' + $('#m').val());
socket.emit('chatmessage', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chatmessage', function (msg) {
console.log('index.html(socket.on)==' + msg);
$('#messages').append($('<li>').text(msg));
});
Html body is
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" />
<button>Send</button>
</form>
When I ran your code I got the following errors in my log files on my gear on OpenShift Online:
Option log level is not valid. Please refer to the README.
Option polling duration is not valid. Please refer to the README.
So I commented out the following lines in your index.js file:
io.set('log level', 1); // reduce logging
io.set('transports', ['xhr-polling']);
io.set("polling duration", 10);
And it seems to be working fine now. You can test it here: http://nodejs-cdaley.rhcloud.com/
And you can view the code here: https://github.com/developercorey/nodejs
Related
I've a node api(POST)in which the sensor keep on pushing the data to the MongoDB. Now I've an api(GET) which fetches the data from the database and displays on the dashboard. To get the continuous stream of data, I want to use SOCKET.IO module. But the problem is, how could I get the recently saved record from the db and show that on dashboard without reloading the page. Please have a look at my code.
SERVER.JS
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
// and manything like router, middleware, etc...
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on port:3000');
});
ROUTES FILE
var router = require("express").Router();
router.post("/upload/device/data/:tempId", TemplateController.AddDeviceData); //To insert the data to the DB
router.get("/view/template/device/logs/:tempUniqID", TemplateController.deviceLogs); //To get the data from DB
TEMPLATE CONTROLLER FILE
module.exports={
AddDeviceData:async function(req, res){ //Controller to post data
let err, deviceLog;
[err, deviceLog]=await
to(TemplateService.AddDeviceLogs(req.params.tempId, req.body));
if(err) return res.serverError(err.message);
if(deviceLog&&deviceLog!==false){
return res.ok(deviceLog);
}else{
res.badRequest("Sorry cannot add Device log data");
}
},
deviceLogs: async function(req, res){ //Controller to fetch data
let err, logs;
let deviceId = req.query.device;
[err, logs]=await to(TemplateService.displayLogs(req.params.tempUniqID, deviceId));
if(err) return res.serverError(err.message);
if(logs&&logs!==false){
return res.ok(logs);
}else{
res.badRequest("Sorry cannot add Device log data");
}
}
}
TEMPLATE SERVICE FILE
module.exports={
//Service to post data
AddDeviceLogs:async function(templateId, payload){
let err, deviceData;
payload.template=templateId;
const myCollection=templateId;
[err, deviceData]=await to(mongoose.connection.db.collection(myCollection).insert(payload));
if(err) TE(err.message, true);
socket.emit('data', deviceData);
return (deviceData)? deviceData.result:false;
},
//Service to get data
displayLogs:async function(tempUniqID, deviceID){
let err, respData;
var Query = (deviceID)? {"template": tempUniqID, "deviceId": deviceID}:{template: tempUniqID};
[err, respData]=await to(mongoose.connection.db.collection(tempUniqID).find(Query).sort({_id: -1}).limit(20).toArray())
if(err) {TE(err, true);}
return (respData)? respData:false;
}
}
Now I want to get most recently stored data in GET api using socket without reloading the page or without executing the GET route-api. I'm not getting which service I should use server socket-emit event in and how.
You can run node and your socket io in the same port, the following example used express and socket.io. I also created sensor code to imagine this solution:
You should use your route file like this:
ROUTES FILE
var router = require("express").Router();
router.post("/upload/device/data/:tempId", TemplateController.AddDeviceData);
router.get("/", function (req, res, next) {
res.sendFile('C:/Users/user/Desktop/data.html');
})
In MVC you will have a root file declare all works, you should delare your socket here.
Because in your codebase, every time you call AddDeviceLogs function, it will re-declare websocket, and your socket client in html file will disconnect, that's why it only work for the first time.
Then you should declare it global, for example:
server.js
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
// and manything like router, middleware, etc...
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on port:3000');
});
TEMPLATE SERVICE FILE
module.exports={
AddDeviceLogs:async function(templateId, payload){
let err, deviceData;
payload.template=templateId;
const myCollection=templateId;
io.emit('data', payload) // emit to all client
[err, deviceData]=await to(mongoose.connection.db.collection(myCollection).insert(payload));
if(err) TE(err.message, true);
return (deviceData)? deviceData.result:false;
}
}
data.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>
</head>
<body>
<script>
var socket = io.connect("http://localhost:3000/",{"forceNew": true});
socket.on('data', function(data){
if (data) {
$('#deviceid').text(data.deviceId);
$('#heat').text(data.heat);
$('#humidity').text(data.humidity);
}
});
</script>
<h4>Welcome to socket.io testing program!</h4>
<div id="deviceid"></div>
<div id="heat"></div>
<div id="humidity"></div>
</body>
</html>
I am trying to implement a chat to a view on my Angular / NodeJS website.
The website is deployed on a server running on port 4200, the backend runs on 8000 and for now the chat socket.io template runs on 3000.
I have followed the socket.io's official chat tutorial in detail so I have a functionnal chat page that works on port 3000 but how can I implement it to an Angular component?
Here is my code so far:
server.js:
const app = require('express')();
var http = require('http').Server(app);
var http2 = require('http').Server(app);
var io = require('socket.io')(http2);
http.listen(8000, function(){
console.log('listening on *:8000');
});
http2.listen(3000, function(){
console.log('listening on *:3000');
});
const home = require('./home.js');
const chat = require('./chat.js');
// SOCKET.IO for testing purpose, following the tutorial
app.get('/', function(req, res){
res.sendFile(__dirname + '/socket.html');
});
io.on('connection', function(socket){
...
});
chat.component.html:
<!doctype html>
<html>
<body>
...
<div class="bottom">
<form action="">
<input id="m" class="messageInput" autocomplete="off"/>
<button type="button" class="btn btn-primary btn-lg btn-block">SEND</button>
</form>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(e){
e.preventDefault(); // prevents page reloading
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
</body>
</html>
I can't figure out to make the chat 'module' work on my HTML page without accessing it through a route (app.get('/', function(req, res){ res.sendFile(__dirname + '/socket.html') });
What can I do? Thanks! And sorry for being a noob :p
Socket.io is different for client side, It's called socket.io-client. You need to get it using:
npm install socket.io-client
Well, Martin you don't need to explicitly link script file in the html. You just need to import socket.io-client variable in its typescript file.
import * as io from 'socket.io-client'. //And then connect using
try {
this._socket = io.connect(socket.io_port_you_are_using_in_server.js)
}
catch (e) {
console.log('error')
}
Now you can use this._socket wherever required like you are doing in server.js.
I also created an app like you using MEAN stack 7 months ago, but I preferred using service as I have to use chat feature in more than 3 components. I'm giving you some sample code which might help you.
joinRoom(room: string, handler: string): Observable<any> {
this._socket.emit('join', { 'room': room, 'handler': handler });
setTimeout(()=>{
console.log(this._socket.id)
},10)
let observable = new Observable((observer) => {
this._socket.on('new user', (data) => {
observer.next(data);
})
})
return observable;
}
leaveRoom(room: string) {
this._socket.emit('leave', room);
this._socket.removeAllListeners()
}
getMessages(): Observable<any> {
let observable = new Observable((observer) => {
this._socket.on('get message', (data) => {
observer.next(data);
})
})
return observable;
}
Just subscribe to the service and use binding to display msgs on the template.
//create array of received msgs
received: any[] = [];
//And in ngOnInit lifecycle hook:
this._chatService.getMessages().subscribe((data) => {
this.received.push(data.msg )
Now you can use *ngFor in the template to display msgs.
<p *ngFor="let msg of received">msg</p>
You can customize code as per your requirement.
Good luck dude!
I'm trying to come to terms with how WebSockets work in Node.js but I'm having some trouble with sending a message.
I have my WebSocket server configured as follows (index.js)
var ws = require("ws");
var wsserver = new ws.Server ({
server: httpserver,
port: 3030
});
wsserver.on (
"connection", function connection(connection) {
console.log("connection");
}
);
wsserver.on (
"open", function open(open) {
console.log("open");
}
);
wsserver.on (
"message", function message(message) {
console.log("message");
}
);
This seems to be working ok because I can establish the connection using
var wscon = new WebSocket("ws://192.168.20.88:3030");
Which then gives me the connection output on the server. If I try to use send though nothing seems to happen and no error messages
wscon.onopen = function(open) {
wscon.send("test message");
}
I must be missing something but I don't know what
I might have an answer for this but I'm not entirely sure just yet, I'm going to put this here just in case.
I think the problem is that the message listener is added to the wrong object (the server object), I tried to add the message listener to the connection object passed to the server and it seems to be working but I'm not 100% sure why
wsserver.on (
"connection", function connection(connection) {
console.log("connection");
connection.on (
"message", function message(message) {
console.log("message : " + message);
}
);
}
);
Which dependency works for me?
I have been using socketIO for a while now and it works perfectly for Node.JS API's / servers. There are millions of tutorials online for this framework and I'll tell you one them.
How to install?
If you use NPM as your package manager in Node.JS just down it with the following command:
npm install --save socket.io
In case you're using yarn you can install socketIO as following:
yarn add socket.io
Setup the socket server:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
// Used for serving the HTML page (if used)
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
// Listen for new connections
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Now in index.html I add the following snippet before the :
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
In your front-end you are able to fire of an event via the socket by calling the following function / code:
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
});
</script>
In our case we emitted an event called chat message. So in order to receive the value send over the socket connection we call the following code in our backend / api:
io.on('connection', function(socket){
socket.on('chat message', function(msg){
console.log('message: ' + msg);
});
});
and that is basically how you use socket with the library SocketIO. Hope this helped fixing your issue!
In my routes.js file I have a route to /test as follows:
app.get('/test', function(req, res, next) {
res.sendFile(__dirname + '/test.html');
var nsp = io.of('/test');
console.log(nsp);
nsp.on('connection', function(socket){
console.log('connection made');
socket.on('new_task', function(msg){
nsp.emit('new_task', msg);
});
});
});
In test.html I have attempted a connection to the /test namespace
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('/test');
$('.exp_addtask').click(function(){
socket.emit('new_task', $('#m').val());
$('#m').val('');
});
socket.on('new_task', function(msg){
$('#messages').append('<div class="task-item"><div class="toggle"></div><p>' + msg + '</p></div>');
});
</script>
There are no errors on runtime and I see all details of the nsp connection when I access http://localhost/test, but what I can't see is that a connection has been made when the page is accessed. Can't see any of the sockets triggering either as they would in the global namespace.
EDIT: At the end of index.js here is how I bring in routes and start the server:
require('./routes')(app);
http.listen(80, function(){
console.log('listening on *:80');
});
Any help is much appreciated.
Finally got it working, don't need to put anything in the routes section (didn't work either if I put it outside the /test route handler)
This successfully works now when I access /test:
var test = io.of('/test');
test.on('connection', function (socket) {
console.log('connection to test');
});
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 :( .