NodeJS & WebSocket learn ip and port of client - node.js

Suppose that i have two of applications which is written below:
server.js
const express = require('express');
const app = express();
const WebSocketServer = require('ws');
var http = require('http');
let server = http.createServer(app).listen(8000);
const wss = new WebSocketServer.Server({ server: server })
// Creating connection using websocket
wss.on("connection", (ws, req) => {
console.log("req.socket.localPort = ", req.socket.localPort);
console.log("req.socket.remotePort = ", req.socket.remotePort);
console.log("req.socket.remoteAddress = ", req.socket.remoteAddress);
console.log("new client connected");
// sending message
ws.on("message", data => {
console.log(`Client has sent us: ${data}`)
});
// handling what to do when clients disconnects from server
ws.on("close", () => {
console.log("the client has connected");
});
// handling client connection error
ws.onerror = function () {
console.log("Some Error occurred")
}
});
and i have a "client" with same code base (code example) which listens port 8001.
Undoubtly, client's open address is 'ws://localhost:8001' and server's 'ws://localhost:8000'. When i make request to server from client,
console.log("req.socket.remotePort = ", req.socket.remotePort);
prints different ports after each message sending. But i want to get the number of 8001. How i can get the number of client's actual port of 8001?

Related

Express and Websocket to run on the same port on the same file

I'm running two apps that sends real-time messages to each other using websocket and also generate a random link using express.js, now i hosted the server with both react apps to my vps host and want to make the websocket connection secure (wss://) but i realize i'll have to get the express server on the same port too, so the ssl/tsl works for both - so how do i do that?
Here is my full code, all on the same file:
const webSocketServerPort = 8000;
const webSocketServer = require('websocket').server;
const http = require('http');
const server = http.createServer(); server.listen(webSocketServerPort); console.log('Listening on port 8000');
const wsServer = new webSocketServer({ httpServer: server })
//GEERTOOOO
const express = require('express'); const cors = require('cors'); const fs = require('fs'); const app = express();
app.use(cors({ origin: '*' }));
app.get('/', (req, res) => { // Generate a random 6-character string const linkId = Math.random().toString(36).substr(2, 6);
// Save the link in the lex.json file fs.readFile('lex.json', (err, data) => { if (err) { console.error(err); res.status(500).send('Error generating link'); return; }
const links = JSON.parse(data);
links[linkId] = {
destination: 'http://localhost:4000/',
expires: Date.now() + 1000 * 60 * 5 // expires in 5 minutes
};
fs.writeFile('lex.json', JSON.stringify(links), (err) => {
if (err) {
console.error(err);
res.status(500).send('Error generating link');
return;
}
// Send the link back to the client
res.send(`http://localhost:3000/${linkId}`);
});
}); });
app.get('/:linkId', (req, res) => {
fs.readFile('lex.json', (err, data) => {
if (err) { console.error(err); res.status(500).send('Error retrieving link');
return;
}
const links = JSON.parse(data);
const link = links[req.params.linkId];
if (!link) {
res.status(404).send('Link not found');
return;
}
// Check if the link has expired
if (link.expires < Date.now()) {
res.status(410).send('Link has expired');
return;
}
// Redirect to the destination
res.redirect(link.destination);
}); });
app.listen(3000, () => { console.log('Server listening on port 3000'); });
//GEERTOOOO
const clients = {};
const getUniqueID = () => { const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return s4() + s4() + '-' + s4(); }
wsServer.on('request', (request) => { var userID = getUniqueID();
const connection = request.accept(null, request.origin); clients[userID] = connection;
connection.on('message', (message) => {
if (message.type === 'utf8') {
for(var key in clients) {
if (clients[key] !== clients[userID]) {
clients[key].sendUTF(message.utf8Data);
console.log(`Sent Message to: ${clients[key]}`);
}
}
}
}) })
Note: the express server is on port 3000 and the websocket server runs on port 8000.
I,ve tried just changing the port to same thing but i get an error when trying to use the websocket server for messages.
THE PURPOSE OF ALL THIS IS JUST TO MAKE THE WEBSOCKET CONNECTION AND EXPRESS CONNECCTION SECURE SO MY APPS (with letsencrypt ssl) can connect to the servers
It is not possible to create two separate server instances, both listening on the same port. But, specifically for a webSocket, you can share one server instance between Express and the webSocket server code. This is possible because a webSocket connection always starts with an http request (thus it can be listened for using your Express http server. And, because these http requests that initiate a webSocket all contain identifying headers they can be separated out from the regular http requests for Express by looking at the headers. The webSocket server code already knows how to do that for you.
To do that, first capture the Express server instance:
const server = app.listen(3000, () => { console.log('Server listening on port 3000'); });
Then, use that server instance when you create your webSocket server.
const wsServer = new webSocketServer({ httpServer: server });
Then, remove this code because you don't want to create yet another http server instance for the webSocket server:
const server = http.createServer();
server.listen(webSocketServerPort);
console.log('Listening on port 8000');

How to send websocket message to client from the serverside

Hello I have two backends laravel and Nodejs
and There will be one frontend.
So if the front end requests something on laravel and laravel requests to node and Node has to send a message to the client through WebSocket.
How to do It?
Index.js
const app = require('express')();
const http = require('http');
const WebSocket = require('ws')
//initialize a simple http server
const server = http.createServer(app);
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
let sendNotification;
//initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
let socketapi = require('./socketapi')
socketapi.start(wss)
//start our server
server.listen(process.env.PORT || 5555, () => {
console.log(`Server started on port ${server.address().port} :)`);
});
socketapi.js
module.exports ={
start: (wss) => {
wss.on('connection', (ws) => {
console.log('connected!!!');
console.log(socketIds)
//connection is up, let's add a simple simple event
// triggerMessage('data');
ws.id=uuidv4()
ws.on('message', (message) => {
console.log('received: %s', message);
// ws.send(`Hello, you sent -> ${message}`);
});
}
}
}
Now I want to use this socket in the controller file and send it as I get a request.
When I export and import socket it logs as undefined.
I have stored and ws in array with particular Id and that Id was associated with data in DB so I can use that Id to get ws and send through that ws on function calling

NodeJS is running one script into another one

I created a TCP server for receiving information from some devices, and I wanted to created an API out from this server, and I exported two variables in order to use them in the API.
When I do that, my server starts in my other process, making that they execute at the same time, I don't know why this happens
//server.js
const { title, BL_url, puerto_controladores, puerto_api } = require('...')
process.title = title;
var net = require('net');
var sockets = [];
var socketsID = [];
var lastConnected = [];
var server = net.createServer( function (socket) {
socket.name = socket.remoteAddress + ":" + socket.remotePort;
sockets.push(socket);
socketsID.push(socket.name.substr(7));
console.log(socket.name + ' connected.');
socket.on('data', (data) => {
textChunk = data.toString('utf8').substr(1,data.toString('utf8').length-2);
console.log('Mensaje de ' + socket.name.substr(7) +
socket.on('close', () =>{
console.log(socket.name + " desconectado.");
});
socket.on('error', (error) =>{
console.log('Error del Cliente TCP: ' + puerto_controladores, error.code, error.message);
});
});
server.on('error', (error) => {
console.log('Error del Server TCP: ' + puerto_controladores, error.message);
});
server.listen(puerto_controladores, ()=>{
setInterval(() => {
webMethods.sendInterval();
}, 180000);
console.log("Server listening at : " + puerto_controladores);
});
//setInterval(()=>{
module.exports = {sockets,socketsID};
On the other hand:
const {sockets,socketsID} = require('..server.js');
const {titleProcess,port} = require('...');
process.title = titleProcess;
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.listen(port, () => {
console.log('Listening at :',port);
});
app.get('/',(req,res)=>{
console.log(test.sockets,test.socketsID);
res.status(200).json({
mensaje: 'received',
})
})
Whatever I do in the server.js, a print of module.export, a new variable, including the title of process in command prompt etc. it runs in the API.js console
//API Output:
Server listening at : 9006
Listening at : 4002
{ sockets: [], socketsID: [] }
{ sockets: [], socketsID: [] }
//Server Output:
Error del Server TCP: 9006 listen EADDRINUSE: address already in use :::9006
Well socket objects in nodejs belong to a particular process. You can't just share them with another process easily. If you want one process to cause data to be sent on a socket the other process owns, then send the data itself to the other process using a different server and send some identifier with the data that the receiving process can use to figure out which socket the data should be sent to and it will then send the data over the socket it has. But, this whole thing sounds like a really confusing way to do things.
For example, let's say you have serverTCP (the plain TCP server from your server.js) and serverAPI (an Express server from your other file) each in separate processes. Put a separate Express server in serverTCP running on a local port, not open to the outside world. When serverAPI receives some data for some socketID, it then makes an http request to serverTCP and sends the data and the socketID. serverTCP receives that http request, gets the socketID and the data out of that request and sends it out over the appropriate socket it has a connection to.
FYI, this is generically known as a proxy where your API is somewhat serving as a proxy for the real socket connection. There are all sorts of modules in NPM that implement actual proxies too.

Cannot connect to socket.io connection in node.js

I'm new to node.js and, having worked through the relevant parts of the Wexler book, I am trying to create a simple stream using socket.io.
Here is my node.js server code:
const port = 3000,
dataIntervalMillis = 5000,
express = require("express"),
app = express(),
crypto = require('crypto');
const server = app
// .get("/", (req, res) => {
// res.send("Run this project by typing in <b>nodemon</b> in the node.js command prompt.");
// })
.listen(port, () => {
console.log(`RNG Server running on port number ${port}`);
}),
io = require("socket.io")(server);
io.on("connection", client => {
console.log("RNG client connected.");
io.emit("New RNG client connection.");
client.on("disconnect", () => {
console.log("RNG client disconnected.");
io.emit("RNG client disconnected.");
});
});
I have built a standalone Java application to test the stream:
//import java.io.BufferedReader;
import java.io.InputStream;
//import java.io.InputStreamReader;
//import java.io.PrintStream;
import java.net.Socket;
public class SimpleSocketClientExample {
public static void main(String[] args) {
String server = "localhost";
int port = 3000;
try {
// Connect to the server
System.out.println("Connect to server " + server + " on port " + port + "...");
Socket socket = new Socket( server, port );
System.out.println("...connected.");
//BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
InputStream in = socket.getInputStream();
System.out.println("Reading byte...");
int b = in.read();
System.out.println("...byte read.");
// Close our streams
if (in != null) {
in.close();
}
if (socket != null) {
socket.close();
}
}
catch( Exception e ) {
e.printStackTrace();
}
}
}
The problem is that this client code hangs on the in.read() line.
The only console log from the server is RNG Server running on port number 3000. There is no RNG client connected in the server log, which indicates that the client has not connected (or has connected to something else).
I've tested my node.js app using online socket testers, and they don't seem to connect either - indicating the problem probably lays with my node.js server app.
Can anyone advise what I may have missed?
Turns out socket.io doesn't create a standard TCP socket.
My solution was to leave my client code untouched and change the Node.js server code to use the net library instead.
In case it might help anyone else that runs into the same issue, here's my new code:
const port = 3000;
const { createServer } = require('net');
const server = createServer();
// A counter to facilitate assigning of socket.id.
let counter = 0;
// An array of connected client sockets that we will broadcast to.
let sockets = {};
server.on('connection', (socket) => {
socket.id = counter++;
console.log(`A client has connected: ${socket.id}`);
// Catch errors so they don't stop the application.
socket.on('error', function () {
console.log(`Client error: ${socket.id}`);
delete sockets[socket.id];
});
// Set character encoding.
socket.setEncoding('utf8');
// Add socket to array.
sockets[socket.id] = socket;
// When connection ends, remove socket from array.
socket.on('end', data => {
console.log(`${socket.id} has disconnected`)
delete sockets[socket.id];
});
});
server.listen(port, () => {
console.log(`RNG Server running on port number ${port}`);
});

Simple node.js socket server

I am trying to create a simple node.js server that will allow my socket based iOS app to send it's GPS coordinates to the server, and the server will broadcast the GPS coordinate to all connected iOS clients. Similarly, the clients are connected to the server using sockets. I tried using some sample code from Heroku's web server. CODE IS EDITED TO INCLUDE ANURAG'S ANSWER
var WebSocketServer = require("ws").Server
var http = require("http")
var express = require("express")
var app = express()
var port = process.env.PORT || 5000
app.use(express.static(__dirname + "/"))
var server = http.createServer(app)
server.listen(port)
console.log("http server listening on %d", port)
var wss = new WebSocketServer({server: server})
console.log("websocket server created")
var connectionList = [];
wss.on("connection", function(ws) {
console.log("connection");
connectionList.push(ws);
})
wss.on("message", function(data, id) {
var mes = server.unmaskMessage(data);
var str = server.convertToString(mes.message);
console.log(str);
var i;
for(i = 0; i < connectionList.lenth; i++) {
wss.sendMessage(one, str, connectionList[i]);
}
});
How do I modify this code to be able to receive messages from my app (via sockets) and then send that message to all other iOS clients connected. (The message is just a simple string)
BONUS QUESTION: Because Heroku makes you use it's environments port (rather than your own specified one), in my iOS app, when I connect to the server, would I just specify the Port that is printed to the console when the server is started.
Any help is appreciated, Thank you! :)
EDIT: For broadcasting to the clients, the code is:
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(message);
});
});
However how do I receive messages from a client, and how do I make the received message the message to be broadcasted to the other clients.
On getting the connection you need to store those connections.
Then you can send message to all those devices connect to your server using those connections.
You may try something like this:
var connectionList = [];
wss.on("connection", function(ws) {
connectionList.push(ws);
})
wss.on("message", function(data, id) {
var mes = server.unmaskMessage(data);
var str = server.convertToString(mes.message);
console.log(str);
var i;
for(i = 0; i < connectionList.lenth; i++) {
wss.sendMessage(one, str, connectionList[i]);
}
});
Read more here: https://www.npmjs.com/package/websocketserver
Here is the complete index.js code sothat the server brodcast received messages to clients:
var WebSocketServer = require("ws").Server
var http = require("http")
var express = require("express")
var app = express()
var port = process.env.PORT || 5000
app.use(express.static(__dirname + "/"))
var server = http.createServer(app)
server.listen(port)
console.log("http server listening on %d", port)
var wss = new WebSocketServer({server: server})
console.log("websocket server created")
wss.broadcast = function(data) {
for (var i in this.clients)
this.clients[i].send(data);
};
wss.on("connection", function(ws) {
console.log("websocket connection open");
ws.on('message', function(message) {
console.log("message received by server");
wss.broadcast(message);
})
ws.on("close", function() {
console.log("websocket connection close")
})
})

Resources