NodeJS and socket.io chat customization - node.js

I have a basic chat system working with NodeJS, express, and socket.io. Now I want to have the server insert the date into the chat stream every 5 seconds. Since this isn't initiated by the user, I am having trouble with the basic request. I am new to NodeJS and maybe it is just a syntax thing that I don't understand. Anyways, with this current code, the date only gets inserted after someone sends a chat message through. I want this to happen automatically on the server side. If no one is chatting, the date will still come through to the client every 5 seconds. My problem most likely stems from the comment section title: "How do I get my periodic timer in here..." Instead I am trying to insert it at the bottom where it says - "//***This section sends out the notification..." Do I structure the functions differently or something? Thanks in advance.
Server.js
var express = require('express'),
app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server);
// listen for new web clients:
server.listen(8080);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.get('/sio/socket.io.js', function (req, res) {
res.sendfile('/root/nodejs/node-v0.10.0/node_modules/socket.io/lib/socket.io.js');
});
//How do I get my periodic timer in here so it can send the date every 5 seconds?
io.sockets.on('connection', function (socket) {
socket.on('sendMessage', function (data) {
socket.broadcast.emit('message', data);
socket.emit('message', { text: '<strong>'+data.text+'</strong>' });
});
});
// Periodic Running
var coolerInterval = function(func, interval, triggerOnceEvery) {
var startTime = new Date().getTime(),
nextTick = startTime,
count = 0;
triggerOnceEvery = triggerOnceEvery || 1;
var internalInterval = function() {
nextTick += interval;
count++;
if(count == triggerOnceEvery) {
func();
count = 0;
}
setTimeout(internalInterval, nextTick - new Date().getTime());
};
internalInterval();
};
coolerInterval(function() {
showdate = new Date().getTime();
console.log( showdate );
//Go ahead and send a notification to everyone.
//***This section sends out the notification that a pick was made
io.sockets.on('connection', function (socket) {
socket.on('sendMessage', function (data) {
socket.broadcast.emit('message', showdate);
});
});
//***End sending out notification.
}, 1000, 5);
//End Periodic
Here is the html in the browser - index.html
<html>
<body>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
var socket = io.connect('http://dev.mysite.com:8080');
socket.on('message', function (data) {
$('#chat').append(data.text + '<br />');
});
$('#send').click(function () {
socket.emit('sendMessage', { text: $('#text').val() });
$('text').val('');
});
});
</script>
<div id="chat" style="width: 500px; height: 300px; border: 1px solid black">
</div>
<input type="text" name="text" id="text">
<input type="button" name="send" id="send" value="send">
</body>
</html>

It's much simpler than you're making it. You can just setInterval() to 5 seconds, and call io.sockets.emit(), which will send the message to all connected sockets.
setInterval(function() {
io.sockets.emit('message', (new Date()).getTime());
}, 5000);
Do this on line 18, and delete everything below there.

Related

How do I establish a peer connection inside a room with socket.io-p2p?

I'm storing my connections withing arrays and I have a button (not included here) which when clicked, places the first two connections inside a room.
I want to establish a p2p connection between those two and transfer some random text or an alert over p2p.
Does anyone have an idea on how I should do that?
Note that I'm loading the socket.io-p2p script in the html so that I don't have to use browserify in this case.
client file:
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script src="http://localhost:8000/js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io('http://localhost:8000');
var p2p = new P2P(socket);
socket.on('C1Trigger', function (data) {
document.getElementById("A").style.backgroundColor = "green";
});
socket.on('C2Trigger', function (data) {
document.getElementById("A").style.backgroundColor = "green";
});
socket.on('C1BYellowTrigger', function (data) {
document.getElementById("B").style.backgroundColor = "yellow";
});
socket.on('C2BGreenTrigger', function (data) {
document.getElementById("B").style.backgroundColor = "green";
});
</script>
</head>
<body>
<div id="A">A</div>
<div id="B">B</div>
</body>
<style>
div {
background-color: #FF0000;
border: none;
color: white;
padding: 30px 60px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 60px;
}
</style>
</html>
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 8000;
//P2P Requirements
var p2p = require('socket.io-p2p-server').Server;
io.use(p2p);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/client.html');
});
app.get('/js', function (req, res) {
res.sendFile(__dirname + '/socketiop2p.min.js');
});
clients = [];
clientSockets = [];
io.on('connection', function (socket) {
clientSockets.push(socket);
console.log('Client: ' + socket.id + ' connected.');
clients.push(socket.id);
io.sockets.emit('clients', clients);
// console.log(clients);
socket.on('executeC1', function () {
console.log('C1 in MainRoom pinged!');
io.to(clients[0]).emit('C1Trigger');
});
socket.on('executeC2', function () {
console.log('C2 in MainRoom pinged!');
io.to(clients[1]).emit('C2Trigger');
});
socket.on('greenifyBC2', function () {
io.to(clients[1]).emit('GreenifyTrigger');
});
socket.on('executeC1C2', function (data) {
console.log('C1C2 in MainRoom pinged!');
clientSockets[0].join('room C1C2', () => {
//expand with features
});
clientSockets[1].join('room C1C2', () => {
//expand with features
});
io.to(clients[0]).emit('C1BYellowTrigger');
io.to(clients[1]).emit('C2BGreenTrigger');
console.log(io.sockets.adapter.rooms);
});
socket.on('disconnect', function () {
console.log('Client: ' + socket.id + ' disconnected');
var index = clients.indexOf(socket.id);
if (index > -1) {
clients[index] = undefined;
}
console.log(clients);
});
});
http.listen(port, function () {
console.log('listening on *:' + port);
});
I would use your socket.io rooms to establish a signal for webrtc. Then I would use webrtc for the p2p connection.
Old question, but I am trying to figure out the same thing. According to the documentation The trick is to use tell the P2P Server to do signaling in rooms for the newly connected socket in the on('connection') of the server code:
io.on('connection', function(socket) {
clients[socket.id] = socket
var room = findOrCreateRoom() //create a room (needs a property called name)
socket.join(room.name) // join the socket
p2pserver(socket, null, room) //tell the P2P server to have that socket signal to other
// sockets in the room and not on the common namespace.
})
Hopefully this will help people find that part of the documentation.
I am trying to figure out how to start signaling only after sockets people are in a room. So not immediately on connection. Not sure how to "pause" signaling...
Update
socket.io-p2p https://github.com/socketio/socket.io-p2p is no longer maintained, and thus is no longer compatible with required npm packages. Use another P2P library.

React and Socket.io: Able to get initial data - but view doesn't update when a new post comes in

Not sure if the issue is how I have my sockets setup - or if I am incorrectly trying to render the data with React.
I can successfully pull in data with my socket - yet it doesn't live update state when new data is posted to the server. My intention is for the state in React to automatically render new data, which is always live because of the socket connection.
Here is my client app that gets messages from the server and renders them:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
<MessageForm submitMessage={this.submitMessage}/>
</div>
);
}
});
Just in case here is my server code that emits data:
io.on('connection', function (socket) {
socket.on('getMessages', function (data) {
Message.find(function(err, messages){
socket.emit('serverMessages', messages);
})
});
});
As of right now, you're "just" grabbing data from the server once the component has been loaded. To get something a bit more "real time" you'll want to either ping the server with the same emit statement you specified regularly (which defeats the point of using websockets, really, you could use long-polling) or have the server regularly send new data to all clients.
You can do EITHER:
A) Client side: "Polling" for information [Not Ideal]
Note: I initially put this in my answer because I saw the OP was "polling" when the controller was loaded. I didn't click on that this might be because the controller may not be loaded with the websocket so sending data on connect might not work here. My bad.
Replace socket.emit('getMessages') with something that will "poll" the websocket regularly for data:
setInterval(function () {
socket.emit('getMessages')
}, 10000); /* Request data from the socket every 10 seconds */
OR
B) Server side: Send new data as it becomes available. [Best Way]
Track all clients via a clients array and delete them from it when their session ends.
var clients = [];
io.on('connection', function (socket) {
clients.push(socket);
socket.on('end', function () {
// Could also splice the array below, but it still works.
delete clients[clients.indexOf(socket)];
});
/* Previous logic for server goes here */
});
Run this code when you need to push new messages from the database/data storage:
for (var i in clients) {
clients[i].emit('serverMessages', /* messages object */);
}
Your server code is only firing upon initial socket connection.
Server:
socket.on('getMessages', function (data) {
Message.find(function(err, messages){
socket.emit('serverMessages', messages);
})
});
Client:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
</div>
);
}
});
Based on naming convention, it also appears that your Message.find() is pulling a single message. I would recommend clarifying the labeling to match cardinality.
Try this:
var Chat = React.createClass({
getInitialState: function() {
return {
messages: null
}
},
componentWillMount: function(){
var self = this;
socket.emit('getMessages');
socket.on('serverMessages', function (data) {
self.setState({messages: data})
});
},
render: function() {
var messages = this.state.messages ? <MessageList messages={this.state.messages}/> : null
return (
<div className="jumbotron">
{ messages }
<MessageForm submitMessage={this.submitMessage}/>
</div>
);
}
});
Could it be possible its due to the componentWillMount lifecycle method? Could you try the componentDidMount instead.
It looks like render will see the state update but only gets executed once despite the state change according to facebook.

In Node.js how to send message to client side from a handler/callback method

I am a beginner in node.js. I am trying to create a webapp using node.js which will create servers in cloud and manage them. After doing some research I've decided to use node.js, socket.io, express and pkgcloud modules to create the webapp. Now, the problem I am facing is that I am unable to send messages to the front-end/client-side when a server is getting created. The server is getting created successfully but I am not getting how to send the server status to the browser screen.
Here's the code:
index.js
var express = require('express'),
app = express();
app.use(express.static(__dirname + '/'));
var io = require('socket.io').listen(app.listen(1337));
io.sockets.on('connection', function(socket) {
socket.on('mesg_to_server', function(data) {
// This is for testing whether we're receiving msgs on client side
io.sockets.emit("mesg_to_client",{ mesg: data["mesg"], mesg1: data["mesg1"] });
var Rackspace = require('./ex_rackspace');
var rackspace = new Rackspace();
rackspace.create(data.mesg);
});
});
ex_rackspace.js:
var pkgcloud = require('pkgcloud'),
_ = require('./node_modules/pkgcloud/node_modules/underscore');
var client = pkgcloud.providers.rackspace.compute.createClient({
username: 'xxxx',
apiKey: 'xxxxx',
region: 'HKG'
});
// This function will handle our server creation,
// as well as waiting for the server to come online after we've
// created it.
function handleServerResponse(err, server) {
if (err) {
console.dir(err);
return;
}
console.log('SERVER CREATED: ' + server.name + ', waiting for active status');
// Wait for status: ACTIVE on our server, and then callback
server.setWait({ status: server.STATUS.running }, 5000, function (err) {
if (err) {
console.dir(err);
return;
}
console.log('SERVER INFO');
console.log(server.name);
console.log(server.status);
console.log(server.id);
console.log('Make sure you DELETE server: ' + server.id +
' in order to not accrue billing charges');
});
}
var Rackspace = function() {
};
Rackspace.prototype.test = function (text) {
console.log("provider: Rackspace: " + text);
}
// first we're going to get our flavors
Rackspace.prototype.create = function (server) {
client.getFlavors(function (err, flavors) {
if (err) {
console.dir(err);
return;
}
// then get our base images
client.getImages(function (err, images) {
if (err) {
console.dir(err);
return;
}
var flavor = _.findWhere(flavors, { name: '1 GB Performance' });
var image = _.findWhere(images, { name: 'CentOS 5 (PV)' });
// Create our first server
client.createServer({
name: server,
image: image,
flavor: flavor
}, handleServerResponse);
});
});
}
module.exports = Rackspace;
page.html (client-side):
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
// our socket.io code goes here
var socketio = io.connect("127.0.0.1:1337");
socketio.on("mesg_to_client", function(data) {
document.getElementById("chatlog").innerHTML = ("<hr/>" +
data.mesg + ' ' + data.mesg1 + document.getElementById("chatlog").innerHTML);
});
socketio.on("test_output", function(data) {
console.log(data.mesg);
});
function sendMessage() {
var msg = document.getElementById("mesg_input").value;
socketio.emit("mesg_to_server", { mesg : msg, mesg1 : "here"});
}
</script>
</head>
<body>
<input type="text" id="mesg_input"/>
<button onclick="sendMessage()">Create</button>
<div id="chatlog"></div>
</body>
</html>
You need to add a callback to the create function
Rackspace.prototype.create = function (server, callback){
//your code - if err send error else send success message
callback(err, message)
}
Then use it when you call create
rackspace.create(data.mesg, function (err, message){
//your code with your socket emit here
});

How to communicate simultaneously in both ways on socket.io node.js

I want to send some data to a node.js server when some event triggers. In parallel, the server is supposed to send some data every 1 second to the client. I am using socket.io for this. Here is my code:
Server side:
app= require('http').createServer(handler).listen(3000),
io = require('socket.io').listen(app);
// request handler function, will send client file which include sliders and graph
function handler (req, res) {
var reqObj = urr.parse(req.url, true);
var reqPath = reqObj.pathname;
if ('/' == reqPath ) {
res.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile(__dirname + '/client.html', function(err, data) {
if (err) {
res.writeHead(500);
return
res.end('Errorloadingclient.html'); }
res.end(data);
}); } };
var slider1, slider2, slider3, slider4 ;
io.sockets.on('connection', function(socket) {
// receive changed value of slider send by client
socket.on('ValSlider1', function(data){
slider1 = data ;
console.log("Slider 1 Value: " + data); });
// same for three more sliders });
// send received values back to client after every 1 second interval
setInterval(function () {
var data = slider1 + "-" + slider2 + "-" + slider3 + "-" + slider4;
socket.emit('packet', data);
},1000); });
app.maxConnections = 1;
Client side:
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript"
src="http://smoothiecharts.org/smoothie.js"></script>
// slider
<p id="ValSlider1"> Curr Val </p>
<input class = "mySlider1" type="range" name="slider" id="slider-0" value="0" min="0" max="100" />
// similar for three more sliders
Packet
var socket = io.connect('http://localhost');
// send changed value to server
$(".mySlider1").change(function() {
var sVal = $(this).val();
socket.emit('ValSlider1', sVal);
});
// similar for three more sliders
socket.on('packet', function (data) {
var valFromServer = data.split('-');
document.getElementById("ValSlider1").innerHTML = valFromServer[0];
});
</script>
Now, I get data on the server side only when I use 'socket.emit()' twice in the client, where the server sends data at 1 second intervals.
finally i manage to do it in this way,
On server side
app= require('http').createServer(handler).listen(3000),
io = require('socket.io').listen(3001);
publisher = require('socket.io').listen(app);
On client side
var socket = io.connect('http://localhost:3001');
var socket2 = io.connect('http://localhost');
client will send data to server on 'socket', in response server will also send some data on same port. simultaneously, server will publish data on 3001 port at every 1 second interval which is received in client on ".on('data')" event of server1.

Server client communication Node.js

I have written a server program server.js as below
var SerialPort = require("serialport").SerialPort
var io = require('socket.io').listen(80);
var serialPort = new SerialPort("COM4", {
baudrate: 9600
});
serialPort.on("open", function () {
console.log('open');
serialPort.on('data', function(data) {
console.log('data received: ' + data);
});
serialPort.write("ls\n", function(err, results) {
console.log('err ' + err);
console.log('results ' + results);
//io.sockets.emit('message', 'data');
});
});
io.sockets.on('connection', function (socket) {
// If socket.io receives message from the client browser then
// this call back will be executed.
socket.on('message', function (msg) {
console.log(msg);
});
// If a web browser disconnects from Socket.IO then this callback is called.
socket.on('disconnect', function () {
console.log('disconnected');
});
});
var cleanData = ''; // this stores the clean data
var readData = ''; // this stores the buffer
serialPort.on('data', function (data) { // call back when data is received
readData += data.toString(); // append data to buffer
// if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
// as clean data. Then clear the buffer.
if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
readData = '';
io.sockets.emit('message', cleanData);
}
});
The client side program is (index.html)
<html>
</head>
<link type="text/css" href="/css/smoothness/jquery-ui-1.8.20.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="//localhost:8000/socket.io/socket.io.js"></script>
<script type="text/javascript" src="/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="/js/jquery-ui-1.8.20.custom.min.js"></script>
<script>
var socket = io.connect('http://localhost:8000');
socket.on('connect', function () {
socket.on('message', function (msg) {
// Convert value to integer
var val = ((parseInt(msg) / 1023)*100);
// Put sensor value to the 'sensor_value' span
$('#sensor_value').html(val);
});
});
});
</script>
</head>
<body>
<div role="main">
Potentiometer Value: <span id="sensor_value"></span><br/>
</div>
</body>
</html>
I am using WAMP as web server
The server console is giving me the required output. But nothing is coming in the webpage index.html
Here you can find a tutorial showing exactly what you're trying to do: create a Node.js server and forwarding data from serial port to an html page via Websockets.
It was very useful to me when doing the same, sure it will help.

Resources