I have made a Module in Node JS. In which I am pushing a Message from One user to another Using Different Web Browsers.
In CMD Console its working properly and message is sending. But it is not showing on Client Page.
Here is the CMD Output:
Here is My Node Server Code:
var app = require('http').createServer(),
io = require('socket.io').listen(app),
fs = require('fs'),
mysql = require('mysql'),
connectionsArray = [],
connection = mysql.createConnection({
host : 'localhost',
user : 'admin',
password : 'admin',
database : 'test',
port : 3306
}),
POLLING_INTERVAL = 3000,
pollingTimer;
// If there is an error connecting to the database
connection.connect(function(err) {
// connected! (unless `err` is set)
console.log( err );
});
// creating the server ( localhost:8000 )
app.listen(8000);
/*
*
* HERE IT IS THE COOL PART
* This function loops on itself since there are sockets connected to the page
* sending the result of the database query after a constant interval
*
*/
var pollingLoop = function () {
// Doing the database query
var query = connection.query('SELECT * FROM users'),
users = []; // this array will contain the result of our db query
// setting the query listeners
query
.on('error', function(err) {
// Handle error, and 'end' event will be emitted after this as well
console.log( err );
forwardMessage( err );
})
.on('result', function( user ) {
// it fills our array looping on each user row inside the db
users.push( user );
})
.on('end',function(){
// loop on itself only if there are sockets still connected
if(connectionsArray.length) {
pollingTimer = setTimeout( pollingLoop, POLLING_INTERVAL );
//updateSockets({users:users});
}
});
};
// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on( 'connection', function ( socket )
{
console.log('Number of connections:' + connectionsArray.length);
// starting the loop only if at least there is one user connected
if (!connectionsArray.length)
{
//pollingLoop();
}
socket.on('addUser', function (id)
{
socket.id = id;
console.log('Here I am. My User ID is: '+socket.id);
socket.emit( 'notification' , 'ok' );
});
socket.on('disconnect', function ()
{
var socketIndex = connectionsArray.indexOf( socket );
console.log('socket = ' + socketIndex + ' disconnected');
if (socketIndex >= 0)
{
connectionsArray.splice( socketIndex, 1 );
}
});
socket.on('sendMessage', function (message)
{
console.log( 'Wow I got a New Message:'+message+' sent by: '+socket.id );
socket.emit( 'notification' , message );
//insertion in db
// get concerned ids to pass notification
var users = new Array();
users.push('777');
// call forwardMessage to send notifications...
forwardMessage(users,message);
});
console.log( 'A new socket is connected!' );
connectionsArray.push( socket );
});
var forwardMessage = function ( users, message )
{
connectionsArray.forEach(function( userSocket )
{
if(inArray(userSocket.id,users))
{
userSocket.volatile.emit( 'notification' , message );
}
});
function inArray(needle, haystack) // In_Array Function For Javascript
{
var length = haystack.length;
for(var i = 0; i < length; i++)
{
if(haystack[i] == needle)
return true;
}
return false;
}
}
And here is my Client Code:
<script>
// create a new websocket
var socket = io.connect('http://localhost:8000');
// on message received we print all the data inside the #container div
socket.on('notification', function (data)
{
//alert('got notification : '+data);
$('#container').html('Got ');
});
socket.emit('addUser','<?php echo $_GET['id']; ?>');
//----------------- SEND MESSAGE FUNCTION -------------------------//
function sendMESSAGE()
{
var message = $("#message").val();
socket.emit('sendMessage',message);
}
</script>
Can anyone tell me what am I doing wrong here or missing here ?
Related
So I have a little server going in Electron, using net and with this class:
var net = require('net')
class Server {
constructor(port) {
this.Port = port
var HOST = '127.0.0.1' // todo: get ip from host name
this.Server = net.createServer();
this.Server.listen(port, HOST);
this.Server.on('connection', (sock) => {
console.log('CONNECTED: ' + sock.remoteAddress + ':' + sock.remotePort);
sock.on('data', function (data) {
console.log( `client sent data ${data}`)
sock.write( `Server sends back ${data} to client`)
});
sock.on('close', function (data) {
let index = sockets.findIndex(function (o) {
return o.remoteAddress === sock.remoteAddress && o.remotePort === sock.remotePort;
})
console.log('CLOSED: ' + sock.remoteAddress + ' ' + sock.remotePort);
});
});
} // constructor
}
and I call it thus:
var server = new Server( 3000 )
testing it with telnet localhost 3000. And it all works dandy but it's kind of tied into a question and answer thing, only sending a response to the client when it's received data from the client in io('data'). Is there any way to send data from, say, outside the class, in a more arbitrary way. As in, for example:
var server = new Server( 3000 )
this.Server.write( data )
This seems to work:
in the this.Server.on('connection') in the constructor:
this.Socket = sock
add the method:
Send( msg ) {
if ( !this.Socket ) {
console.log( "Server.Send(): no client connected" )
}
this.Socket.write( msg )
}
and in sock.on( 'close' ) set the socket method back to null:
this.Socket = null
then:
var server = new Server( 3000 )
server.Send( data )
(needs a check for a connection)
I am trying to run this program in Raspberry Pi 3.
I have installed nodejs and ws on my raspberry pi.
Then I installed serial port module.
I am trying to create this project:enter link description here
I have tried to find solutions everywhere but I could not find one.
If any one knows how to solve this problem please help me.
var webSocketUrl = "wss://api.artik.cloud/v1.1/websocket?ack=true";
var device_id = "5bb3ba9304674086bee67fa507a215cf"; //DEVICE ID
var device_token = "36b278345b6d4d11abf764ae213c5c70"; //DEVICE TOKEN
var WebSocket = require('ws');
var isWebSocketReady = false;
var data="";
var ws = null;
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var sp = new SerialPort("/dev/ttyACM0", { //for serial communication with arduino
baudrate: 9600,
// The baud rate of uno is 9600
parser: serialport.parsers.readline("\n")
});
/**
* Gets the current time in millis
*/
function getTimeMillis(){
return parseInt(Date.now().toString());
}
/**
* Create a /websocket connection and setup GPIO pin
*/
function start() {
//Create the WebSocket connection
isWebSocketReady = false;
ws = new WebSocket(webSocketUrl);
ws.on('open', function() {
console.log("WebSocket connection is open ....");
register();
});
ws.on('message', function(data) {
//this loop is called whenever the client sends some message
handleRcvMsg(data); //data is send to the function handleRcvMsg()
});
ws.on('close', function() {
console.log("WebSocket connection is closed ....");
});
}
/**
* Sends a register message to /websocket endpoint
*/
//Client will only work when device gets registered from here
function register(){
console.log("Registering device on the WebSocket connection");
try{
var registerMessage = '{"type":"register", "sdid":"'+device_id+'", "Authorization":"bearer '+device_token+'", "cid":"'+getTimeMillis()+'"}';
console.log('Sending register message ' + registerMessage + '\n');
ws.send(registerMessage, {mask: true});
isWebSocketReady = true;
}
catch (e) {
console.error('Failed to register messages. Error in registering message: ' + e.toString());
}
}
//data after receiving is sent here for processing
function handleRcvMsg(msg){
var msgObj = JSON.parse(msg);
if (msgObj.type != "action") return; //Early return;
var actions = msgObj.data.actions;
var actionName = actions[0].name; //assume that there is only one action in actions
console.log("The received action is " + actionName);
}
/**
* Send one message to ARTIK Cloud
*/
//This function is responsible for sending commands to cloud
//function sendStateToArtikCloud(parking,temperature,water){
function sendDataToArtikCloud(pantry){
var result=pantry.split(" ");//data gets split by " " to get the values
try{
ts = ', "ts": '+getTimeMillis();
var data = {
"Garlic": result[1],
"Potato":result[2],
"Temperature":result[3],
"Chilli":result[4],
"Humidity": result[5],
"Ginger":result[6],
"Onion": result[7]
};
var payload = '{"sdid":"'+device_id+'"'+ts+', "data": '+JSON.stringify(data)+', "cid":"'+getTimeMillis()+'"}';
console.log('Sending payload ' + payload + '\n');
ws.send(payload, {mask: true});
} catch (e) {
console.error('Error in sending a message: ' + e.toString() +'\n');
}
}
function exitClosePins() {
console.log('Exit and destroy all pins!');
process.exit();
}
start();
//exectes every second when data is received from arduino (5sec programmed delay from arduino)
sp.on("open", function () {
sp.on('data', function(data) {
console.log("Serial port received data:" + data);
//var result=data.split(" ");//data gets split by " " to get the values
//sendStateToArtikCloud(result[0],result[2],result[1]);//parking,temperature,waterlevel
sendDataToArtikCloud(data);
});
});
process.on('SIGINT', exitClosePins);
I am getting an error on my raspberry pi
enter image description here
Suggest me a solution.
The documentation will tell you that Readline is spelled with a capital R
https://www.npmjs.com/package/serialport#module_serialport--SerialPort.parsers
parser: serialport.parsers.Readline("\n")
~
[TypeError: serialport.parsers.readline is not a function.]
If it has not been resolved yet, try this method.
var serialport = require("serialport")
var SerialPort = serialport.SerialPort;
var sp = new serialport("/dev/ttyACM0"),{
BaudRate: 9600,
parser: new serialport.parsers.Readline("\r\n")
});
I hope your problem is solved.
So, every time I refresh the page, it seems like sockjs is creating a new connection.
I am saving every message to my mongodb on every channel.onmessage, so if I refresh my page 7 times and send a message, I would save 7 messages of the same content into my mongodb.
This is very problematic because when I retrieve those messages when I go into the chat room, to see the log, I would see bunch of duplicate messages.
I want to keep track of all connections that are 'active', and if a user tries to make another connections, I want to be able to force close on the old one from the server side, so there is only 1 connection listening to each message at a time
How do I do this ?
var connections = {};
//creating the sockjs server
var chat = sockjs.createServer();
//installing handlers for sockjs server instance, with the same url as client
chat.installHandlers(server, {prefix:'/chat/private'});
var multiplexer = new multiplexServer.MultiplexServer(chat);
var configChannel = function (channelId, userId, userName){
var channel = multiplexer.registerChannel(channelId);
channel.on('connection', function (conn) {
// console.log('connection');
console.log(connections);
connections[channelId] = connections[channelId] || {};
if (connections[channelId][userId]) {
//want to close the extra connection
} else {
connections[channelId][userId] = conn;
}
// }
// if (channels[channelId][userId]) {
// conn = channels[channelId][userId];
// } else {
// channels[channelId][userId] = conn;
// }
// console.log('accessing channel! ', channels[channelId]);
conn.on('new user', function (data, message) {
console.log('new user! ', data, message);
});
// var number = connections.length;
conn.on('data', function(message) {
var messageObj = JSON.parse(message);
handler.saveMessage(messageObj.channelId, messageObj.user, messageObj.message);
console.log('received the message, ', messageObj.message);
conn.write(JSON.stringify({channelId: messageObj.channelId, user: messageObj.user, message: messageObj.message }));
});
conn.on('close', function() {
conn.write(userName + ' has disconnected');
});
});
return channel;
};
Simply use .close:
if (connections[channelId][userId]) {
// want to close the extra connection
connections[channelId][userId].close();
} else {
connections[channelId][userId] = conn;
}
I'm writing a Node.js application using Express and a PostgreSQL database using node-postgres. I want to look up the current user's username and real name based on their email, and set them in req.session. However, if I set them where I am in the code below, they are undefined when we leave that block (i.e. the first console.log statements print the correct info, the second set prints undefined. How can I solve this?
var client = new pg.Client(app.conString);
var realname = "";
var username = "";
client.connect();
var query = client.query(
"SELECT * FROM users WHERE email = $1;",
[req.session.email]
);
query.on('row', function(row) {
req.session.realname = row.realname;
req.session.username = row.username;
console.log(req.session.realname);
console.log(req.session.username);
});
console.log(req.session.realname);
console.log(req.session.username);
query.on('end', function() {
client.end();
});
The second pair of console.log will execute before the query-results are available (in the row event handler).
If your code is going to be used in an Express route, you would use something like this:
app.get('/', function(req, res) {
var client = new pg.Client(app.conString);
var realname = "";
var username = "";
client.connect();
var query = client.query(
"SELECT * FROM users WHERE email = $1;",
[req.session.email]
);
query.on('row', function(row) {
req.session.realname = row.realname;
req.session.username = row.username;
});
query.on('end', function() {
client.end();
res.send(...); // <-- end the request by sending back a response
});
});
An alternative for using the EventEmitter interface for node-postgres would be to just pass a callback to query (which looks better with Express IMHO):
client.query(
"SELECT * FROM users WHERE email = $1;",
[req.session.email],
function(err, results) {
if (err)
// handle error
else
if (results.length)
{
req.session.realname = results[0].realname;
req.session.username = results[0].username;
}
res.send(...); // done
});
I'm making a chat app with socket.io, and I'd like to use my custom client id, instead of the default ones (8411473621394412707, 1120516437992682114). Is there any ways of sending the custom identifier when connecting or just using something to track a custom name for each ID? Thanks!
You can create an array on the server, and store custom objects on it. For example, you could store the id created by Socket.io and a custom ID sent by each client to the server:
var util = require("util"),
io = require('/socket.io').listen(8080),
fs = require('fs'),
os = require('os'),
url = require('url');
var clients =[];
io.sockets.on('connection', function (socket) {
socket.on('storeClientInfo', function (data) {
var clientInfo = new Object();
clientInfo.customId = data.customId;
clientInfo.clientId = socket.id;
clients.push(clientInfo);
});
socket.on('disconnect', function (data) {
for( var i=0, len=clients.length; i<len; ++i ){
var c = clients[i];
if(c.clientId == socket.id){
clients.splice(i,1);
break;
}
}
});
});
in this example, you need to call storeClientInfo from each client.
<script>
var socket = io.connect('http://localhost', {port: 8080});
socket.on('connect', function (data) {
socket.emit('storeClientInfo', { customId:"000CustomIdHere0000" });
});
</script>
Hope this helps.
To set custom socket id, generateId function must be overwritten. Both of eio and engine props of Socket.io server object can be used for to manage this operation.
A simple example:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.engine.generateId = function (req) {
// generate a new custom id here
return 1
}
io.on('connection', function (socket) {
console.log(socket.id); // writes 1 on the console
})
It seems to be it has been handled.
It must be in mind that socket id must be unpredictable and unique value with considering security and the app operations!
Extra: If socket.id is returned as undefined because of your intense processes on your generateId method, async/await combination can be used to overcome this issue on node.js version 7.6.0 and later. handshake method of node_modules/engine.io/lib/server.js file should be changed as following:
current:
// engine.io/lib/server.js
Server.prototype.generateId = function (req) {
return base64id.generateId();
};
Server.prototype.handshake = function (transportName, req) {
var id = this.generateId(req);
...
}
new:
// function assignment
io.engine.generateId = function (req) {
return new Promise(function (resolve, reject) {
let id;
// some intense id generation processes
// ...
resolve(id);
});
};
// engine.io/lib/server.js
Server.prototype.handshake = async function (transportName, req) {
var id = await this.generateId(req);
...
}
Note: At Engine.io v4.0, generateId method would accept a callback. So it would not needed to change handshake method. Only generateId method replacement is going to be enough. For instance:
io.engine.generateId = function (req, callback) {
// some intense id generation processes
// ...
callback(id);
};
In the newest socket.io (version 1.x) you can do something like this
socket = io.connect('http://localhost');
socket.on('connect', function() {
console.log(socket.io.engine.id); // old ID
socket.io.engine.id = 'new ID';
console.log(socket.io.engine.id); // new ID
});
I would use an object as a hash lookup - this will save you looping through an array
var clients = {};
clients[customId] = clientId;
var lookup = clients[customId];
Do not change the socket IDs to ones of your own choosing, it breaks the Socket.io room system entirely. It will fail silently and you'll have no clue why your clients aren't receiving the messages.
This will work with 2.2.0 and above version of Socket.IO
To set custom Socket Id, generateId function must be overwritten.
A simple example:
Server Side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.use((socket, next) => {
io.engine.generateId = () => {
// USE ONE OF THESE
socket.handshake.query.CustomId; // this work for me
// return socket.handshake.query.CustomId;
}
next(null, true);
});
io.on('connection', function (socket) {
console.log(socket.id);
})
Clint Side
io.connect(URL, { query: "CustomId = CUSTOM ID IS HERE" })
NOTE: Keep in mind that socket id must be a unique value.
why not a simpler solution that does not need to maintain an array of connected clients and does not override internal socket id?
io.on("connection", (socket) => {
socket.on('storeClientInfo', (data) => {
console.log("connected custom id:", data.customId);
socket.customId = data.customId;
});
socket.on("disconnect", () => {
console.log("disconnected custom id:", socket.customId);
})
});
Client side
let customId = "your_custom_device_id";
socket.on("connect", () => {
socket.emit('storeClientInfo', { customId: customId });
});
or you can override the socket id, like this:
io.on('connection', function(socket){
socket.id = "YOUR_CUSTOM_ID";
});
you can see under the array:
io.sockets.sockets
Can store customId (example userId) in object format instead of for loop, this will improve performance during connection, disconnect and retrieving socketId for emitting
`
var userId_SocketId_KeyPair = {};
var socketId_UserId_KeyPair = {};
_io.on('connection', (socket) => {
console.log('Client connected');
//On socket disconnect
socket.on('disconnect', () => {
// Removing sockets
let socketId = socket.id;
let userId = socketId_UserId_KeyPair[socketId];
delete socketId_UserId_KeyPair[socketId];
if (userId != undefined) {
delete userId_SocketId_KeyPair[userId];
}
console.log("onDisconnect deleted socket with userId :" + "\nUserId,socketId :" + userId + "," + socketId);
});
//Store client info
socket.on('storeClientInfo', function (data) {
let jsonObject = JSON.parse(data);
let userId = jsonObject.userId;
let socketId = socket.id;
userId_SocketId_KeyPair[userId] = socketId;
socketId_UserId_KeyPair[socketId] = userId;
console.log("storeClientInfo called with :" + data + "\nUserId,socketId :" + userId + "," + socketId);
});
`
With this 2.2.0 version of Socket.IO, you can achieve this.
io.use((socket, next) => {
io.engine.generateId = () => socket.handshake.query.token;
next(null, true);
});
If you are trying to use a custom id to in order to communicate with a specific client then you can do this
io.on('connection', function(socket){
socket.id = "someId"
io.sockets.connected["someId"] = io.sockets.connected[socket.id];
// them emit to it by id like this
io.sockets.connected["someId"].emit("some message", "message content")
});