NodeJS Websocket (ws) how communicate between different clients? - javascript

I have 2 clients, I need client1 gives information to client2 and this receive an alert of it, I'm implementing Websocket "ws" with NodeJS for this.
Client1 web page receive an answer via AJAX and send information to server.js in JSON format, like this example:
/mysite_folder/client1/client1.php
<script>
var userorder = $("#user").val(); //client2 username who will receive information
$.post("myscript.php",{
my: variables
}).done(function(response){
var wsUri = "wss://www.mysite.com:3000/sockets/";
var output;
websocket = new WebSocket(wsUri);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;
function onOpen(evt){
output = {
"status": "ASSIGNED",
"user": userorder
};
doSend(JSON.stringify(output));
}
function doSend(message){
websocket.send(message);
websocket.close();
}
function onMessage(evt){
}
function onClose(evt){
location.reload();
}
function onError(evt){
}
});
</script>
After client1 send information, connection closes and refresh client1 page. My server receives this JSON information like this: /mysite_folder/sockets/server.js
var WebSocketServer = require('ws').Server,
fs = require('fs');
var cfg = {
ssl: true,
port: 3000,
ssl_key: '/path/of/sslkey',
ssl_cert: '/path/of/sslcert'
};
var httpServ = ( cfg.ssl ) ? require('https') : require('http');
var app = null;
var processRequest = function( req, res ) {
res.writeHead(200);
res.end("All glory to WebSockets!\n");
};
if ( cfg.ssl ) {
app = httpServ.createServer({
// providing server with SSL key/cert
key: fs.readFileSync( cfg.ssl_key ),
cert: fs.readFileSync( cfg.ssl_cert )
}, processRequest ).listen( cfg.port );
} else {
app = httpServ.createServer( processRequest ).listen( cfg.port );
}
var wss = new WebSocketServer( { server: app } );
wss.on('connection', function connection(ws){
console.log("User connected");
ws.on('message', function incoming(message){
var info = JSON.parse(message); //receive client1 info
if(info.status=="ASSIGNED"){
ws.send(info.user); //send client2 username
}
});
});
Parsing JSON and comparing that information status is "ASSIGNED" I need "info.user" send to client2 page displaying an alert message, so in client2 I wrote like this example: /mysite_folder/client2/client2.php
$(document).ready(function(){
var user = $("#user").val(); //client2 username
var wsUri = "wss://www.mysite.com:3000/sockets/";
var output;
websocket = new WebSocket(wsUri);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage;
websocket.onerror = onError;
function onOpen(evt){
}
function doSend(message){
}
function onMessage(evt){
if(user==evt){ //if client2 username sent by server is the same with client2 username logged in the page, make an alert
alert("Your order was ASSIGNED");
}
websocket.close();
}
function onClose(evt){
}
function onError(evt){
}
});
Connections works fine, client1 is working well, but in client2 doesn't happen anything, how can I make client2 get this alert?
UPDATE
On server.js I added a broadcast method like this:
var wss = new WebSocketServer( { server: app } );
// Broadcast to all.
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
if ( client.readyState == WebSocketServer.OPEN) {
client.send(data);
}
});
};
wss.on('connection', function connection(ws){
console.log("User connected");
ws.on('message', function incoming(message){
//Broadcast to everyone else
var info = JSON.parse(message);
console.log(info.user); //shows username in console
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocketServer.OPEN) {
if(info.status=="ASSIGNED"){
client.send(info.user);
}
}
});
});
});
But client2 is still doesn't receiving message from server and not displaying the alert.
I would like some help.

The issue is your sending data back down the same socket connection you receive the message i.e. ws.send(info.user), ws refers to that client connection only.
The server has a broadcast method you can use which sends the message to all active connections
wss.broadcast(info.user);

Related

NodeJS Unable to connect to Websocket Cross origin - "Err 1006"

I have a two webservers both running https with the same certificates, I have a main shard that the user connects to example.com, they retrieve some data and try to connect to an ip address on the 2nd shard via websocket.
But no matter what I configure I get an Error 1006 on the client side when connecting to the 2nd shard. Firefox devtooling gives me multiple errors - ssl_error_bad_cert_domain, SSL_ERROR_RX_RECORD_TOO_LONG.
The certificates are issued and signed, I was wondering where I should go from here. Thanks :)
SHARD2
const options = {
key: './server.key',
cert: './server.cert'
};
var https = require('https').Server(options);
https.listen(443, function () {
// console.log('Https listening on *: 443');
});
let WebSocket = require('ws');
let socket = new WebSocket.Server({ server:https });
socket.on('connection', function (ws, req) {
ws.on('message', (msgRaw) =>{
});
ws.on('close', function(code, reason) {
});
ws.on('error', function(error) {
console.log(error);
ws.close();
});
});
CLIENT
function connect() {
"use strict";
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
alert('Your browser doesn\'t support WebSocket');
return;
}
wss = new WebSocket('wss://123.123.123.120/:443');
wss.onmessage = function(event) {
};
wss.onerror = function(event) {
console.log(`wss error: ${JSON.stringify(event)}`);
};
wss.onclose = function(event) {
};
}
Useful sys diagram?

Firefox can’t establish a connection to the server at wss://localhost:8000/

I am using nodejs to run the server, there is no log file
This is my server.js
const https = require('https');
const fs = require('fs');
const ws = require('ws');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const wss = new ws.Server({noServer: true});
function accept(req, res) {
// all incoming requests must be websockets
if (!req.headers.upgrade || req.headers.upgrade.toLowerCase() != 'websocket') {
res.end();
return;
}
// can be Connection: keep-alive, Upgrade
if (!req.headers.connection.match(/\bupgrade\b/i)) {
res.end();
return;
}
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), onConnect);
}
function onConnect(ws) {
ws.on('message', function (message) {
let name = message.match(/([\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]+)$/gu) || "Guest";
ws.send(`${name}!`);
//setTimeout(() => ws.close(1000, "Bye!"), 5000);
});
}
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
This is my code in react
componentDidMount() {
var connection = new WebSocket('wss://localhost:8000/');
connection.onopen = function(e) {
connection.send("add people");
};
connection.onmessage = function(event) {
// alert(`[message] Data received from server: ${event.data}`);
console.log("output ", event.data);
};
}
While I am trying to connect with web-socket with my jsx file its give me an error which is Firefox can’t establish a connection to the server at wss://localhost:8000/.
Your implementaion needs some changes. In the backend server, you forgot to call the onConnect function. So your ws.on method will never call.
Also, you imported the ws and create a WebSocket server wss, but you add some event listener on ws wrongly, you should add listener on your Websocket instance (wss):
// rest of the codes ...
const was = new ws.Server({noServer: true})
wss.on('connection`) {
// do something here ...
}
// rest of the codes ...
https.createServer(options, () => {
// do something here ...
})
There are some examples of how to create the WebSocket server along with the HTTP server on ws npm page.

Binary stream transfer across multiple socket connections

I have a use case where I need to take input from browser pass it to my node server over a socket, this input is then send to a third party website for processing again over socket. The result received from the third party website needs to be sent back to browser.
node server
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var socketIO = require('socket.io'),
server, io;
var thirdPartSocketClient = require('socket.io-client');
//Custom imports
var thirdParty = require('./ms_socket.js');
var socket = socketIO(server);
socket.on('connection', function(client) {
var token = null;
//Token from third party site that we should have before sending the actual info
thirdParty.getToken(function callback(returnToken) {
token = returnToken;
});
thirdPartSocketClient = thirdParty.getTranslation(token);
client.on('audio', function(data) {
thirdPartSocketClient.emit(data);
});
});
server.listen(8080, function() {
console.log('Open http://localhost:8080 in your browser');
});
ms_socket.js
//Exported function making a socket call to third party service
var exports = module.exports = {};
var request = require('request');
var wsClient = require('socket.io-client');
var fs = require('fs');
exports.getToken = function(callback) {
//send back the token
}
exports.getTranslation = function(accessToken) {
var ws = new wsClient(thirdPartySocketURL);
// event for connection failure
ws.on('connectFailed', function(error) {
console.log('Initial connection failed: ' + error.toString());
});
// event for connection succeed
ws.on('connect', function(connection) {
console.log('Websocket client connected');
// process message that is returned
//processMessage would process the incoming msg from third party service
connection.on('message', processMessage);
connection.on('close', function(reasonCode, description) {
console.log('Connection closed: ' + reasonCode);
});
// print out the error
connection.on('error', function(error) {
console.log('Connection error: ' + error.toString());
});
});
// connect to the service
ws.connect(thirdPartySocketURL, null, null, {
'Authorization': 'Bearer ' + accessToken
});
return ws;
}; //End of export function
I am able to receive the data from browser, make a connection to third party service (can see the socket connection) and emit the data. however I am unable to receive the reply back from the third part service.
Is it because node is not listening to my socket events of thirdparty ?
Not sure exactly why its not working.
I save the data locally on the server, read the file and then send it, then I get a response back from the service.
If this is not a "right" design can you please suggest a good way, should I be using message queues (if yes, feel free to recommend one)
Thanks

How to reuse TCP Client for further use in node.js

I am using a TCP connection via node.js to connect to a certain port in windows, however I want the connection to be established until the user logs out .
In other words I want to add the TCP Connection as a session attribute in node.js ,so that it will last as long as the session is alive for the user.
I have tried this ,but it doesn't work.
Code :
var express = require('express');
var authRouter = express.Router();
var createTCPConnection = function () {
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client
client.write('I am Chuck1 Norris!');
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
// Close the client socket completely
//client.destroy();
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
return client;
};
authRouter.route('/').get(function(req, res) {
var sess = req.session;
if (sess.username) {
//If Session has username attribute, it is a valid session
res.render('dashboard', {
title : 'Welcome To Operator Screen',
username : sess.username
});
if(sess.tcpClient === undefined) {
console.log('Establishing TcpClient');
sess.tcpClient = createTCPConnection();
} else {
console.log('TcpClient already established');
}
} else {
//Invalid/expired session, redirect to homepage
res.redirect('/logout');
}
});
module.exports = authRouter;

How to present the received (by UDP) data from node.js server in the client's browser?

I have the simple node.js server that receives udp packages and prints them in the console:
var PORT = 19777;
var MULTICAST_GROUP = "224.0.0.251";
var dgram = require("dgram");
var payload = new Buffer('A wild message appears');
var client = dgram.createSocket("udp4");
client.on("message", function(message, rinfo) {
console.log("received: ",message);
});
client.on("listening", function() {
console.log("listening on ",client.address());
client.setBroadcast(true);
client.setTTL(64);
client.setMulticastTTL(64);
client.setMulticastLoopback(true);
client.addMembership(MULTICAST_GROUP);
client.send(payload, 0, payload.length, PORT, MULTICAST_GROUP, function(err,bytes) {
console.log("err: "+err+" bytes: "+bytes);
// client.close();
});
});
client.on("close", function() {
console.log("closed");
});
client.on("error", function(err) {
console.log("error: ",err);
});
client.bind(19777);
it works remotely on my server. I want to present the received data to each client that will turn on his browser and enter the address of my server. How could I do that?

Categories

Resources