I am trying to create a server with clients. Each client has a websocket and a web worker, and each worker has an own websocket to the server.
The problem is, that i have a place on the server, where i am storing all connections
wss.on('connection', function connection(ws) {
var cid = "" + ++cid_counter;
server.users[cid] = ws;
...
}
But now they are all storing in server.users[], and i want to store clients sockets in server.users and worker sockets in server.wokers[], but i have no idea, how to distinguish there two different types of web sockets. Maybe i could send a message, when creating a new web socket or any other solutions?
Thanks in forward
You should add auth to your sockets so you can identify the client.
Refer to this: socketio-auth
You can issue unique keys to clients and workers or whoever you want and then require them to emit to "authenticate" event.
You can distinguish them by having a key "type" in the db.
From npm:
Client:
var socket = io.connect('http://localhost');
socket.on('connect', function(){
socket.emit('authentication', {username: "John", password: "secret"});
socket.on('authenticated', function() {
// use the socket as usual
});
});
Server:
var io = require('socket.io').listen(app);
require('socketio-auth')(io, {
authenticate: function (socket, data, callback) {
//get credentials sent by the client
var key = data.key;
db.findUser('Users', {secret: key}, function(err, user) {
//inform the callback of auth success/failure
if (err || !user) return callback(new Error("User not found"));
return callback(null, user);
});
}
});
Related
I'm trying to use websockets with sails-js but I can't make it work with native javascript websockets.
the tutorial example use the sails.io.js library and it goes a little bit like this:
io.socket.on('hello', function (data) {
console.log('Socket `' + data.id + '` joined the party!');
});
function sendHello () {
// And use `io.socket.get()` to send a request to the server:
io.socket.get('/websockets/hello', function gotResponse(data, jwRes) {
console.log('Server responded with status code ' + jwRes.statusCode + ' and data: ', data);
});
}
This does work, but i want to use the native javascript websockets like this:
let ws = new WebSocket("ws://localhost:1337/websockets/hello");
ws.onopen = function (e) {
console.log("[open] Connection established");
console.log("Sending to server");
ws.send("My name is John");
};
ws.onmessage = function (event) {
console.log(`[message] Data received from server: ${event.data}`);
};
ws.onclose = function (event) {
if (event.wasClean) {
console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
console.log('[close] Connection died');
}
};
ws.onerror = function (error) {
console.log(`[error] ${error}`);
console.log(error);
};
Clean and native javascript websockets with no library needed. Unfortunately I can't seem to make it work.
When I try to connect to sails js server using native websockets I get this message:
WebSocket connection to 'ws://localhost:1337/websockets/hello' failed: Connection closed before receiving a handshake response
Impossible to make it connect, it seems like sails js don't even get the message because i make a log when i get a new connection (using the tutorial code):
module.exports = {
hello: function (req, res) {
console.log("web socket received",req.isSocket)
// Make sure this is a socket request (not traditional HTTP)
if (!req.isSocket) {
return res.badRequest();
}
// Have the socket which made the request join the "funSockets" room.
sails.sockets.join(req, 'funSockets');
// Broadcast a notification to all the sockets who have joined
// the "funSockets" room, excluding our newly added socket:
sails.sockets.broadcast('funSockets', 'hello', { howdy: 'hi there!' }, req);
// ^^^
// At this point, we've blasted out a socket message to all sockets who have
// joined the "funSockets" room. But that doesn't necessarily mean they
// are _listening_. In other words, to actually handle the socket message,
// connected sockets need to be listening for this particular event (in this
// case, we broadcasted our message with an event name of "hello"). The
// client-side code you'd need to write looks like this:
//
// io.socket.on('hello', function (broadcastedData){
// console.log(data.howdy);
// // => 'hi there!'
// }
//
// Now that we've broadcasted our socket message, we still have to continue on
// with any other logic we need to take care of in our action, and then send a
// response. In this case, we're just about wrapped up, so we'll continue on
// Respond to the request with a 200 OK.
// The data returned here is what we received back on the client as `data` in:
// `io.socket.get('/say/hello', function gotResponse(data, jwRes) { /* ... */ });`
return res.json({
anyData: 'we want to send back'
});
}
};
How can I make sails js work with native javascript websockets?
Found a simple solution!
Used the npm package ws: npm i ws
making a new hook: sails generate hook customWebSocket
in the hook :
/**
* WS hook
*
* #description :: A hook definition. Extends Sails by adding shadow routes, implicit actions, and/or initialization logic.
* #docs :: https://sailsjs.com/docs/concepts/extending-sails/hooks
*/
const WebSocket = require('ws');
module.exports = function defineWsHook(sails) {
return {
/**
* Runs when this Sails app loads/lifts.
*/
initialize: async function () {
sails.log.info('Initializing custom hook (`WS`)');
console.log("custom hook")
const wss = new WebSocket.Server({ port: 3100 });
wss.on('connection', (socket) => {
console.log('New user connected wss');
socket.on('message', function incoming(message) {
console.log(message)
});
});
}
};
};
Done and done, now i can connect to is using native websocket!
now that i have done that i realize that the socket.io library might be better for handling errors.
With the out of date docs on sails' sockets implementation i'm struggling to get the basic 'connect' message. Here's my node.js server side code:
sails.sockets.on('connection', function(socket){
sails.log.info('socket connected');
//create room and broadcast a welcome message
socket.emit('user joined', {'message': 'Welcome to ' + roomName});
socket.join(roomName);
socket.broadcast.to(roomName).emit('user joined', {'message': 'Welcome to ' + roomName});
});
and my client side:
var sock = io.connect('http://localhost:8888');
sock.on('connection', function(socket){
console.log('conected to server');
});
sock.on('user joined', function (json) {
console.log('socket: ' + json);
});
I do get the OK message from sails itself on start up but can't seem to get a connection of my own:
sails.io.js:200 `io.socket` connected successfully.
(for help, see: http://sailsjs.org/#!documentation/reference/BrowserSDK/BrowserSDK.html)
I tried using socket.io v1 and got the same weird situation. any ideas? thanks!
On server config/sockets.js
module.exports.sockets = {
onConnect: function(session, socket) {
sails.log.verbose('>>> socket user connected');
sails.sockets.blast('eventName', dataToBlast);
},
};
Documentation http://sailsjs.org/#/documentation/anatomy/myApp/config/sockets.js.html
On client
io.socket.on('eventName', function(dataToBlast) {
// process dataToBlast
});
Documentation http://sailsjs.org/#/documentation/reference/websockets/sails.io.js/io.socket.on.html
Be aware that socket needs to be subscribed to eventName. To subscribe you need to make controller SubscribeController.js and make request to it's action via socket.
var SubscribeController = {
sub: function(req, res) {
ModelName.subscribe(
req.socket,
[] /*records to subscribe to or empty array to subscribe to all */,
['eventName'] /* array of strings eventNames */
);
},
};
For debugging client you can connect to firehose which will give your client all messages from sails server
io.socket.get('/firehose');
io.socket.on('firehose', function newMessageFromSails(message) {
typeof console !== 'undefined' &&
console.log('New message published from Sails ::\n', message);
});
My nodejs server is unable to detect when a new browser connects ('connection' event) and I dont know why. I narrowed down a problem working on it for a few days and suspect that is has to due with the addition of the pubnub socket connection implemented on the browser.
The following is my server.js
var http = require('http')
, connect = require('connect')
, io = require('socket.io')
, fs = require('fs')
, uuid = require('node-uuid')
, _ = require('lodash');
// pubnub!!! (how to initialize it for use on server)
var pubnub = require('pubnub').init({
channel: "my_channel",
publish_key: "pub-key",
subscribe_key: "sub-c-key",
uuid: "Server",
origin : 'pubsub.pubnub.com'
});
pubnub.subscribe({
channel: 'my_channel',
callback: function(message) {
console.log("Message received: ", message);
},
message: 'Server ready',
presence: function(data) {
console.log("Presense: ", data);
},
connect: publish
});
// various socket.on() events omitted
var app = connect().use(connect.static(__dirname)).use(connect.directory(__dirname));
var server = http.createServer(app);
server.listen(8888);
io = io.listen(server);
io.sockets.on('connection', handleNewPeer);
Upon arriving on the html page, the doConnect(isBroadcaster) function is ran from script tag
The doConnect function (In peer.js):
var doConnect = function(isBroadcaster) {
console.log("doConnect");
// broadcaster or normal peer
var user;
if (isBroadcaster)
user = "Broadcaster";
else
user = "Viewer";
(function() {
var pubnub_setup = {
channel: "my_channel",
publish_key: "pub-c-key",
subscribe_key: "sub-c-key",
user: user
};
// Note removed the var
socket = io.connect( 'http://pubsub.pubnub.com', pubnub_setup);
// various socket.on() omitted
})();
Here is what how it was before with just socketIO & it was working:
var doConnect = function(isBroadcaster) {
socket = io.connect();
// various socket.on() omitted
}
My p2p video website is implemented with WebRTC running on a Nodejs + SocketIO server.
I have been trying to incorporate pubnub into it & thought it would be easy since pubnub supports SocketIO (or at least client side?). Really did not think it would be this difficult to set up server side.
Any input at all on this? I think it's something simple that I just cannot put my finger on
Socket.IO on the Server using Node.JS
Socket.IO with PubNub does not provide a Node.JS Socket.IO backend option. However you can use the PubNub SDK directly for on-connect events.
NPM Package
npm install pubnub
After you install the PubNub NPM you can use the node.js server backend:
Node.js Backend Code
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// PubNub!!! (how to initialize it for use on server)
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
var pubnub = require('pubnub').init({
publish_key : "pub-key",
subscribe_key : "sub-c-key",
uuid : "Server-ID"
});
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// On user Connect
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
function on_user_connect(data) {
console.log( "User Connected: ", data.uuid );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// On user Leave
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
function on_user_leave(data) {
console.log( "User Left: ", data.uuid );
}
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// Open Socket Connection for User Join Events
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
pubnub.subscribe({
channel : 'my_channel',
connect : connected
message : function(message) {
console.log("Message received: ", message);
},
presence : function(data) {
if (data.action == "leave") on_user_leave(data);
if (data.action == "timeout") on_user_leave(data);
if (data.action == "join") on_user_connect(data);
}
});
function connected() {
console.log('connected!');
}
What version of socket.io are you using?
This might not fix it. I am using version 1.+ Have you tried:
io.on('connection', function(socket){
console.log('user connected');
});
I have a chat, and I need to manage unique connections. I searched around, but the solutions that I have found all appear to be deprecated.
So, how would I get a socket's session ID with Socket.IO?
I'm using Node.js, Express.js and Socket.IO.
Use the Socket.IO authentication setting, and pass the cookies to the cookie parser middleware from Express. Once the cookie is parsed, you can get the session ID of the client, and fetch the associated session from the session store, whether it is a memory story or other type of store.
// we need to use the same secret for Socket.IO and Express
var parseCookie = express.cookieParser(secret);
var store = /* your MemoryStore, RedisStore, etc */;
io.set('authorization', function(handshake, callback) {
if (handshake.headers.cookie) {
// pass a req, res, and next as if it were middleware
parseCookie(handshake, null, function(err) {
handshake.sessionID = handshake.signedCookies['connect.sid'];
// or if you don't have signed cookies
handshake.sessionID = handshake.cookies['connect.sid'];
store.get(handshake.sessionID, function (err, session) {
if (err || !session) {
// if we cannot grab a session, turn down the connection
callback('Session not found.', false);
} else {
// save the session data and accept the connection
handshake.session = session;
callback(null, true);
}
});
});
} else {
return callback('No session.', false);
}
callback(null, true);
});
Each time a client attempts to connect, the authorization function is run. It takes the handshake header cookies (handshake.headers.cookies), and passes them to express.cookieParser(). The cookie parser then finds the session ID, and then searches the store for the associated session. Then, we store the associated session into handshake.session, so we can access it like this:
app.get('/', function(req, res) {
req.session.property = 'a value';
});
io.sockets.on('connection', function(socket) {
var session = socket.handshake.session;
session.property // a value
});
I am writing a simple app in Node that will collect search queries on client side, send it to Node server and from server to admin page where I can track 'em. However I want to keep in mind security so I want to send search queries from Node ONLY to admin page. This is what I have so far:
Node Server:
var socket = io.listen(app);
socket.on('connection', function(client){
client.on('message', function(data){
socket.broadcast(data);
});
});
Client:
$.getScript('http://127.0.0.1:8000/socket.io/socket.io.js', function() {
var socket = new io.Socket('127.0.0.1', {'port': 8000});
socket.connect();
socket.send(search_query);
});
});
Admin:
$(document).ready(function(){
socket = new io.Socket('172.20.14.114', {port: 3000});
socket.connect();
socket.on('message', function(data){
console.log(data);
});
});
The code above works perfectly but I want to pipe 'search_query' ONLY to the admin page (due to security reasons). Now my Node server broadcasts data everywhere. How do I modify my script? Thanks in advance.
I'd have the admin send a message to the server (something more secure than 'AdminLogin') to register as admin, then you can simply send to that one client.
Server:
var socket = io.listen(app), admin;
socket.on('connection', function(client){
client.on('message', function(data){
if( data === 'AdminLogin' ) {
admin = client;
}
if( admin ) {
admin.send(data);
}
});
});
Admin:
$(document).ready(function(){
socket = new io.Socket('172.20.14.114', {port: 3000});
socket.connect();
socket.send('AdminLogin');
socket.on('message', function(data){
console.log(data);
});
});