How to use websocket npm library in browser? - node.js

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.

Related

Socket hang up when connecting to websocket with Node.JS and a WebSocketsClient

I'm trying to connect to a public websocket to retrieve a stream of data using Node.JS and the WebSocketClient.
Using Chrome extension tools such as WebSocket Test Client and PieSocket Websock Tester, I am able to do this successfully. I can enter the websocket URL, connect and receive am initial header of data and then when I send the required response to initiate the data stream, I can see the data being received every second, as expected.
I then created a simple Node.JS app to do the same as above so that I can get the data from the websocket and work with it but I keep getting a
Connect Error: Error: socket hang up
I have debugged the code and stepped through it but I can't see why this is happening. I can only assume at this point that it's not keeping the connection open but despite researching how to do this, I can't find a way (if indeed this is the issue?).
This is the code I am using so far just to test the retrieval of the data:
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
const _Message = JSON.stringify(
{
Key: '123',
Format: 'JSON'
});
client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
connection.send(_Message);
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendData() {
if (connection.connected) {
console.log("STILL CONNECTED");
}
}
sendData();
});
client.connect('ws://URLofWebsocket:3030/PathToWebsocket/', 'echo-protocol');
I've been trying to fix this issue for 2 days so any advice would be appreciated.
I have tried 2 different Websocket libraries but get the same error.

Two different websockets working together

I'm trying to figure out how to implement a two separate websockets together. Not sure if this possible or not, but I have a websocket that works on it's own in from node.js file to angular another node.js file that uses Kraken (crypto exchange) websocket that also works in it's own file. I'm trying to consolidate them both together so that whenever a event onChange comes from Kraken websocket, I can relay that data to angular with angular socket.io websocket. Trying to do something like this
const webSocketClient = new WebSocket(connectionURL);
webSocketClient.on("open", function open() {
webSocketClient.send(webSocketSubscription);
});
webSocketClient.on("message", function incoming(wsMsg) {
const data = JSON.parse(wsMsg);
let io = require("socket.io")(server, {
cors: {
origin: "http://localhost:4200",
methods: ["GET", "POST"],
allowedHeaders: ["*"],
credentials: true,
},
});
io.on("connection", (socket) => {
const changes = parseTrades(data);
socketIo.sockets.emit(connection.change, changes);
Log whenever a user connects
console.log("user connected");
socket.emit("test event", JSON.stringify(changes));
});
console.log("DATA HERE", data[0]);
});
webSocketClient.on("close", function close() {
console.log("kraken websocket closed");
});
Although doing this doesnt relay the data to frontend and gives me a memory leak. Is there some way I can accomplish this?
I would probably split up the task a little bit. So have a service for the kraken websocket and maybe a service for your own socket, then have them communicate via observables, that you can also tap into from the front end to display data you want.
#Injectable()
export class KrakenService{
private webSocketClient : WebSocket | null;
private messages$ = new BehaviorSubject<any>(null); // give it a type
openConnection(){
// is connectionUrl from environment ??
this.webSocketClient = new WebSocket(connectionURL);
webSocketClient.on("open", function open() {
/// is webSocketSubscription from environment ??
webSocketClient.send(webSocketSubscription);
});
webSocketClient.on("message", function incoming(wsMsg) {
const data = JSON.parse(wsMsg);
this.messages$.next(data);
console.log("DATA HERE", data[0]);
});
webSocketClient.on("close", function close() {
console.log("kraken websocket closed");
this.webSocketClient = null;
});
}
getKrakenMessages(){
if(webSocketClient == null) this.openConnection();
return messages$.asObserbable();
}
}
So now when you want to either read the web socket messages or use them with the other socket you just subscribe to the krakenService.getKrakenMessages();
Then you can do something similar with you local service as well. Have something that opens connections, and one that emits messages. The example you showed it would open up a connection every time you got a message, so keep those logics separated. And reuse existing connection.

Node Websockets Broadcast not working

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.');
});

Using Socket.IO in MeteorJS Server

i am trying top get socket.io working from the MeteorJS server. i am using the package from https://github.com/joncursi/socket-io-client, but i am unable to get it to work from the server and i cant figure out why.
i call the "connectToServer" method from the client, then this should contact the remote server and initialise the connection. when the code executes, i can see that the messages being logged, but nothing inside the "socket.on('connect',..." method. this suggests that it isn't making the connection. this is backed up by the fact that when i run code from the client side (using the the socket.io browser javascript code), i am able to connect without issues.
i have code on the server, whever there is an attempt to connect to the socket.io connection. this logged, with the client side code but not the server side code.
can anyone see what i may be doing wrong here?
Meteor.methods({
'connectToServer': function() {
socketioController();
}
});
function socketioController(){
var username = 'asd';
var password = 'asd';
console.log("trying to login with asd");
var socket = io('https://localhost:3001/');
console.log("socket variable set");
socket.on('connect', Meteor.bindEnvironment(function() {
console.log('Connected to the websocket!');
//Meteor.call('methodName1');
// on data event
socket.on('data-event', Meteor.bindEnvironment(function(data) {
console.log(data);
Meteor.call('methodName2');
}, function(e) {
throw e;
}));
// on disconnect
socket.on('disconnect', Meteor.bindEnvironment(function() {
console.log('Disconnected from the websocket!');
Meteor.call('methodName3');
}, function(e) {
throw e;
}));
}, function(e) {
throw e;
}));
}

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