Node Websockets Broadcast not working - node.js

Currently having an issue with "Broadcast" not seeming to function properly with a super simple websocket setup I started in Node. This is my first time working with websockets so I may be missing something pretty apparent, but after looking online for a while I wasn't able to find a resolution.
Basically I am just trying to have the ability to push some json out to all currently connected Clients.
I can confirm that that socket is working because I am able to see the static connection string on 'ws.send' in the 'connection' block when I connect at ws://localhost:3000, as well as seeing mulitple clients logged out from the broadcast method if I connect with multiple clients.
Any help as to what I may be missing would be greatly appreciated,
var WebSocketServer = require('uws').Server;
var wss = new WebSocketServer({ port: 3000 }); // ws://localhost:3000
// Static test var
var test_message = {
'test': 'Response',
'test2': 'Response2'
};
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
console.log('IT IS GETTING INSIDE CLIENTS');
console.log(client);
// The data is coming in correctly
console.log(data);
client.send(data);
});
};
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(test_message);
console.log('Received: ' + message);
});
// TODO This is static just to check that the connection is properly working
ws.send('You successfully connected to the websocket.');
});

I tested your code with Smart Websocket Client. Your code is fine. If you broadcast data having string only, then you can see the reply in UI, but for javascript object, the client doesn't display although you can see response as Binary Frames (opcode = 2) in Chrome Developer Tools.
The reason behind this behavior is that the ws.send() method support normal strings, typed arrays or blobs, but sending typed arrays and blobs will result in the frame(s) received by the client as binary frames (opcode = 2).
You can try JSON.stringify the object,
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(JSON.stringify(test_message));
console.log('Received: ' + message);
});
ws.send('You successfully connected to the websocket.');
});

Related

How to use websocket npm library in browser?

I started learning node.js. I want to make a chat application using websockets. In console it's working fine. But in browser i'm getting
Uncaught ReferenceError: require is not defined
I googled and saw this answer. I want to try browserify but it's not working properly. Here is my js file
client.js:
var WebSocket = require('websocket');
var connector;
var WebSocketClient = WebSocket.client;
var client = new WebSocketClient();
client.on('connectFailed', function (error) {
console.log('Connect Error: ' + error.toString());
setTimeout(self.connect, 2000);
});
client.on('connect', function (connection) {
connector = connection;
console.log('WebSocket Client Connected');
connection.on('error', function (error) {
errorStr = error.toString();
console.log("Connection Error: " + errorStr);
});
connection.on('close', function () {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function (message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
connection.sendUTF("Hello");
sender("Working");
});
client.on('error', function (err) {
console.log("It's an Err " + err.toString());
});
function connect() {
client.connect('ws://localhost:8765/', 'echo-protocol');
}
function sender(str) {
connector.sendUTF(str);
}
connect();
Here is the problem. When I run bunddle.js.
$ browserify client.js > bunddle.js
$ node bunddle.js
/home/user/udb/sgg/node/chat/bundle.js:5
var client = new WebSocketClient();
^
TypeError: undefined is not a function
The websocket library you are using involves some native C++ bindings. These are incompatible with browserify so you cannot use it. You should use the library only in your server-implementation and in your client.js that runs in the browser you should use the WebSocket object.
Browsers provide their own WebSocket object. The websocket NPM package you are using is a Node.js implementation of the browser-standard WebSocket interface (Well, the websocket.W3CWebSocket class anyway).
Essentially in browsers you should not need require('websocket') or anything similar as the browsers already provide you with the WebSocket. See the MDN example for an example of using WebSockets in the browser.
Of course given WebSockets provide a communication method between two endpoints, you will need an endpoint with which your browser will communicate. This is where you need a package like the websocket: Implementing the server-side endpoint with which the browser communicates.
From the doc itself:
https://github.com/websockets/ws
Note: This module does not work in the browser. The client in the docs is a reference to a back end with the role of a client in the WebSocket communication.
Browser clients must use the native WebSocket object. To make the same code work seamlessly on Node.js and the browser
you can use one of the many wrappers available on npm, like isomorphic-ws.
The native api and implementation is just cool and sufficient
(don't see a motivation for isomorphic-ws)
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
init
webSocket = new WebSocket(url, protocols);
const ws = new WebSocket("wss://www.example.com/socketserver");
send and json
You need to JSON.stringify. And ws in the backend will handle it all right.
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send
ws.send(JSON.stringify(data));
Events
Note that you don't have the on('event') api
But instead
onopen, onmessage, onclose, ... methods to set
ws.onmessage = function (event) {
console.log(event.data);
}
Or by using events and addEventListner
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
The total events are: open, close, message, error.
And it's nice to look out the doc, and also the tutorial here
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications
Install the websocket npm module with npm install websocket. Then write this at the beginning of the file, where you need the client.
var WebSocketClient = require('websocket').client;
NOTE: Browserify creates own scopes for all files when bundeling them. so WebSocketClient is not available in the scope, where it is used.

Is node.js net server data event object a buffer?

I'm attempting to make a tcp game server in node.js but am having problems with data transmission. I want to get the length (in bytes) of the buffer i receive in the sockets DATA event so logically, under the assumption that the object is a buffer (from what i've read) i tried this :
var server = net.createServer();
server.on("connection", function(socket) {
socket.on("data", function(data) {
console.log(data.length);
});
});
But apparently it returns undefined. This confused me quite alot so i tried to see if i'm even handling a buffer here by doing this :
var server = net.createServer();
server.on("connection", function(socket) {
socket.on("data", function(data) {
console.log(Buffer.isBuffer(data));
});
});
And i got false! Could anybody explain what i'm doing wrong?
ps. i have no encoding set on the socket
This code is fine. I messed up somewhere else!

Creating a server listening on a `net` stream and reply using Node.js

Can someone give me a working example on how to create a server listening on the stream and reply when there is a request coming through.
Here's what I have so far:
var port = 4567,
net = require('net');
var sockets = [];
function receiveData(socket, data) {
console.log(data);
var dataToReplyWith = ' ... ';
// ... HERE I need to reply somehow with something to the client that sent the initial data
}
function closeSocket(socket) {
var i = sockets.indexOf(socket);
if (i != -1) {
sockets.splice(i, 1);
}
}
var server = net.createServer(function (socket) {
console.log('Connection ... ');
sockets.push(socket);
socket.setEncoding('utf8');
socket.on('data', function(data) {
receiveData(socket, data);
})
socket.on('end', function() {
closeSocket(socket);
});
}).listen(port);
Will the socket.write(dataToReplyWith); do it?
Yes, you can just write to the socket whenever (as long as the socket is still writable of course). However the problem you may run into is that one data event may not imply a complete "request." Since TCP is just a stream, you can get any amount of data which may not align along your protocol message boundaries. So you could get half a "request" on one data event and then the other half on another, or the opposite: multiple "requests" in a single data event.
If this is your own custom client/server design and you do not already have some sort of protocol in place to determine "request"/"response" boundaries, you should incorporate that now.

Using Socket.io, how do I detect when a new channel/room has been created?

From the server, I want to be able to detect when a client creates new a room or channel. The catch is that the rooms and channels are arbitrary so i don't know what they will be until the user joins/subscribes. Something like this:
Server:
io.on('created', function (room) {
console.log(room); //prints "party-channel-123"
});
Client:
socket.on('party-channel-123', function (data) {
console.log(data)
})
I also can't have any special client requirements such as sending a message when the channel is subscribed as such:
socket.on('party-channel-123', function (data) {
socket.emit('subscribed', 'party-channel-123');
})
Server:
io.sockets.on('connection', function(socket) {
socket.on('createRoom', function(roomName) {
socket.join(roomName);
});
});
Client
var socket = io.connect();
socket.emit('createRoom', 'roomName');
the io object has references to all currently created rooms and can be used as such:
io.sockets.in(room).emit('event', data);
Hope this helps.
PS. I know its emitting the 'createRoom' that you probably don't want but this is how socket.io is used, this is pretty much copy/paste out of the docs. There are tons of examples on the socket.io website and others.

Socket IO emitting multiple times (equal to number of clients connected) using sails js

I am trying to develop a simple socket io based chat app using sails MVC.
whenever a client connected socket emitting multiple times(equa to number of clients).
here is my code.
Server :
io=req.socket.manager;
var users=[];
io.sockets.on('connection', function(client) {
console.log("connected");
users.push(client.id);
client.on("chat", function(data) {
io.sockets.sockets[data.to].emit("chat", { from: client.id, to: data.to, msg: data.msg });
client.emit("chat", { from: client.id, to: data.to, msg: data.msg });
});
});
Client :
var socket=new io.connect('http://localhost:1337/');
socket.request('/Chat/index');
socket.emit('connection',function(data){
console.log(data);
});
socket.on('connect', function() {
console.log("Connected.");
//
});
socket.on('chat', function(data) {
console.log(data.msg );
});
please help me , is there any way to get actual socket object in sails?
I am using io=req.socket.manager; which is of req object.
the socket object should be accessible in sails.io on the server side
link
maybe you want to answer to a unique socket id? that can be achieved this way:
In the file sockets.js, at your config folder, find the onConnect property and add code like this:
onConnect: function(session, socket){
sails.io.sockets.socket(socket.id).send('YOUR_EVENT', {'message' : 'your message to a unique socket'});
}
It will send a unique message when a new connection is established. Just a couple of notes:
This can be considered a socket.io issue, not a sails issue, since the method .socket(socket.id) is part of socket.io
This was tested on sails v0.9.8, in other versions the file sockets.js might not be included in the default generated app with sails' new command
This is just an example to show how can it be done, you might need to adapt it to your needs.
Hope this helps.

Resources