I am writing server client application in node js.
Unfortunately Socket io connection is not being established.
My server side code is like this.
filename : MyServer.js
function MyServer(selectClient)
{
var express = require('express');
var bodyParser = require("body-parser");
this.app = express();
this.app.use(bodyParser.urlencoded({ extended: false }));
this.app.use(bodyParser.json());
var cookieParser = require('cookie-parser')
this.app.use(cookieParser())
if (undefined == selectClient)
{
selectClient = "default";
}
this.setStaticRoute("client/" + selectClient);
this.client = selectClient;
};
MyServer.prototype.setStaticRoute = function (staticPath)
{
var express = require('express');
var path = require('path');
this.app.use(express.static(staticPath));
};
MyServer.prototype.listen = function (portNumber)
{
this.server = this.app.listen(portNumber, '127.0.0.1', function ()
{
var MyServerSocketIo = require('MyServerSocketIo');
this.socketLink = new MyServerSocketIo(this.server,this.onDisconnect.bind(this),
this.onError.bind(this),this.onConnection.bind(this));
console.log("Inside listen function");
}.bind(this));
};
MyServer.prototype.onDisconnect = function()
{
console.log('On Socket IO Disconnect for MyServer');
};
MyServer.prototype.onError = function()
{
console.log('On Error');
};
MyServer.prototype.onConnection = function()
{
console.log('On Connection');
};
and MyServerSocketIo.js is like below
function MyServerSocketIo(server,onDisconnectCB,onErrorCB,onConnectionCB)
{
var SocketIo = require('socket.io');
this.onDisconnectCB = onDisconnectCB;
this.onErrorCB = onErrorCB;
this.onConnectionCB = onConnectionCB;
this.socket = null;
this.socketio = SocketIo(server);
this.socketio.on('connection',this.onConnection.bind(this));
};
MyServerSocketIo.prototype.onDisconnect = function ()
{
console.log('MyServer SocketIO Client Disconnected');
this.onDisconnectCB();
};
MyServerSocketIo.prototype.onError = function (error)
{
console.log('MyServer SocketIO Connection error' + error);
this.onErrorCB();
};
MyServerSocketIo.prototype.onConnection = function (socket)
{
console.log('MyServer SocketIO Connection with Client ID '+ socket.id + ' Established');
this.socket = socket;
socket.on('disconnect', this.onDisconnect.bind(this));
socket.on('error',this.onError.bind(this));
this.onConnectionCB();
};
Below is my client side code
filename: index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<title>visual Display</title>
<link rel="preload" href="css/visual.css" as="style">
<link rel="stylesheet" href="css/visual.css">
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="js/jquery-3.3.1.js"></script>
<script type="text/javascript" src="js/MyClientSocketIo.js"></script>
<script type="text/javascript" src="js/display.js"></script>
<script type="text/javascript" charset="utf-8">
display = new Display();
function OnDisconnect()
{
display.showError();
}
function OnError()
{
display.showError();
}
clientSocket = io.connect('http://localhost:39198', {
transports: ['websocket'],
'forceNew': true,
rejectUnauthorized: false,
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax : 1000,
reconnectionAttempts: 99999
});
var socketClient = new MyClientSocketIo(clientSocket,OnDisconnect,OnError);
</script>
</head>
<body>
</body>
</html>
MyClientSocketIo.js file code is like below
function MyClientSocketIo(client,onDisconnectCB,onErrorCB)
{
this.onDisconnectCB = onDisconnectCB;
this.onErrorCB = onErrorCB;
this.client = client;
this.client.on('connect',this.onConnection.bind(this));
};
MyClientSocketIo.prototype.onDisconnect = function ()
{
console.log('MyClient Disconnected');
this.onDisconnectCB();
};
MyClientSocketIo.prototype.onError = function (error)
{
console.log('MyClient ' + this.client.id + ' encountered Error ' + error);
this.onErrorCB();
};
MyClientSocketIo.prototype.onConnection = function ()
{
console.log('MyClient ' + this.client.id + ' connected to MyServer over SocketIO !!');
this.client.on('disconnect', this.onDisconnect.bind(this));
this.client.on('error',this.onError.bind(this));
};
I could able to see server and client are getting started and below console log "Inside listen function" getting printed as well which is MyServer.prototype.listen function.
But socketIO connection b/w server and client is not getting established.
I could not see console log lines which are there inside MyServerSocketIo.prototype.onConnection function.
I am waiting 30seconds for socketio connection. If not established restarting the server and client and after restarting also socketio connection is not getting established.
This is my personal script of working chat. I have done code with nodejs, axios and socket.
You can do with this script also.
Backend Server
require("dotenv").config();
const port = process.env.SOCKET_PORT || 3000;
const main_server_url = process.env.SERVER_URL;
var express = require("express");
var app = express();
var server = app.listen(port);
var connectionOptions = {
"force new connection": true,
"reconnection": true,
"reconnectionDelay": 2000, //starts with 2 secs delay, then 4, 6, 8, until 60 where it stays forever until it reconnects
"reconnectionDelayMax": 60000, //1 minute maximum delay between connections
"reconnectionAttempts": "Infinity", //to prevent dead clients, having the user to having to manually reconnect after a server restart.
"timeout": 10000, //before connect_error and connect_timeout are emitted.
"transports": ["websocket"] //forces the transport to be only websocket. Server needs to be setup as well/
}
var io = require("socket.io").listen(server, connectionOptions);
var axios = require("axios");
var users = [];
var connections = [];
console.log("Server connected done");
io.sockets.on("connection", function (socket) {
var server_url = main_server_url;
console.log(server_url);
console.log(people);
connections.push(socket);
console.log("Connected : total connections are " + connections.length);
// rest of events of socket
});
Front End JS for load IO for client
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script type="text/javascript">
var base_url = YOUR_BASE_URL;
var port = YOUR_SOCKET_PORT;
var socket_port_url = base_url + ":" + port;
var socket = io(socket_port_url);
socket.on('done', (data) => {
console.log(data);
});
</script>
Related
I'm trying to make a connection between a react client and an express server with websockets. Every time I try this i get an error. I think I'm missing something.
Server code:
var http = require('http');
var ws = require('ws');
var theHttpServer = http.createServer();
var theWebSocketServer = new ws.Server({
server: theHttpServer,
verifyClient: true
});
theHttpServer.on('request', app);
theHttpServer.listen(9000,
function () {
console.log("The Server is lisening on port 9000.")
});
theWebSocketServer.on('connection', function connection(msg) {
console.log("CONNECTION CREATED");
websocket.on('message', function incoming(message) {
});
});
Client code:
let wsConnection = new WebSocket("ws://localhost:9000");
wsConnection.onopen = function(eventInfo) {
console.log("Socket connection is open!");
}
The error:
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
^
TypeError: this.options.verifyClient is not a function
You're passing verifyClient as a boolean, not a function. What you would maybe want to do is change this to:
function verifyClient(info) {
// ...Insert your validation code here
};
var theWebSocketServer = new ws.Server({
server: theHttpServer,
verifyClient: verifyClient
});
I am planning a security system based on tcp. I want to secure it with TLS/SSL. I want to make a Client make a message to the server, the server has to check it and send to all the other clients a message back.
I think it is unclear how to handle that, because the documentation of node.js tls only shows how you connect to the server and get a message back.
This is the code of the documentation:
const tls = require('tls');
const fs = require('fs');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
rejectUnauthorized: true,
};
const server = tls.createServer(options, (socket) => {
console.log('server connected',
socket.authorized ? 'authorized' : 'unauthorized');
socket.write('welcome!\n');
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.listen(8000, () => {
console.log('server bound');
});
Maybe you could make an example, because its totally unclear to me. Thanks for your help. If my question is unclear to you, please let me know.
'use strict';
var tls = require('tls');
var fs = require('fs');
const PORT = 1337;
const HOST = '127.0.0.1'
var options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('public-cert.pem')
};
var users= [];
var server = tls.createServer(options, function(socket) {
users.push(socket)
socket.on('data', function(data) {
for(var i = 0; i < users.length; i++){
if(users[i]!=socket){
users[i].write("I am the server sending you a message.");
}
}
console.log('Received: %s [it is %d bytes long]',
data.toString().replace(/(\n)/gm,""),
data.length); });
});
server.listen(PORT, HOST, function() {
console.log("I'm listening at %s, on port %s", HOST, PORT);
});
server.on('error', function(error) {
console.error(error);
server.destroy();
});
I'm a newbie working with an application with MEAN stack. It is an IoT based application and using nodejs as a backend.
I have a scenario in which I have to send a broadcast to each connected clients which can only open the Socket and can wait for any incoming data. unless like a web-browser they can not perform any event and till now I have already gone through the Socket.IO and Express.IO but couldn't find anything which can be helpful to achieve what I want send raw data to open socket connections'
Is there any other Node module to achieve this. ?
Here is the code using WebSocketServer,
const express = require('express');
const http = require('http');
const url = require('url');
const WebSocket = require('ws');
const app = express();
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
wss.on('connection', function connection(ws) {
ws.on('message', function(message) {
wss.broadcast(message);
}
}
wss.broadcast = function broadcast(msg) {
console.log(msg);
wss.clients.forEach(function each(client) {
client.send(msg);
});
};
server.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
Now, my query is when this code will be executed,
wss.on('connection', function connection(ws) {
ws.on('message', function(message) {
wss.broadcast(message);
}
}
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({port:8100});
wss.on('connection', function connection(ws) {
ws.on('message', function(message) {
wss.broadcast(message);
}
}
wss.broadcast = function broadcast(msg) {
console.log(msg);
wss.clients.forEach(function each(client) {
client.send(msg);
});
};
Try the following code to broadcast message from server to every client.
wss.clients.forEach(function(client) {
client.send(data.toString());
});
Demo server code,
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 2055 },()=>{
console.log('server started')
})
wss.on('connection', (ws) => {
ws.on('message', (data) => {
console.log('data received \n '+ data)
wss.clients.forEach(function(client) {
client.send(data.toString());
});
})
})
wss.on('listening',()=>{
console.log('listening on 2055')
})
I've followed multiple tutorials to set up socketio-jwt, but every time it seems that I'm not getting past this part:
Connected to SocketIO, Authenticating
Any ideas?
Client side:
<h1>Socket Connection Status: <span id="connection"></span></h1>
<script type="text/javascript">
$(document).ready(function () {
socketIOConnectionUpdate('Requesting JWT Token from Laravel');
$.ajax({
url: 'http://localhost:8000/token?id=1'
})
.fail(function (jqXHR, textStatus, errorThrown) {
socketIOConnectionUpdate('Something is wrong on ajax: ' + textStatus);
})
.done(function (result, textStatus, jqXHR) {
socketIOConnectionUpdate('Connected to SocketIO, Authenticating')
/*
make connection with localhost 3000
*/
var token = result.token;
var socket = io.connect('http://localhost:3000');
socket.on('connect', function () {
socket
.emit('authenticate', {token: token}) //send the jwt
.on('authenticated', function () {
console.log('authenticated');
socketIOConnectionUpdate('Authenticated');
})
.on('unauthorized', function(msg) {
socketIOConnectionUpdate('Unauthorized, error msg: ' + msg.message);
throw new Error(msg.data.type);
})
});
});
});
/*
Function for print connection message
*/
function socketIOConnectionUpdate(str) {
$('#connection').html(str);
}
Server side
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var socketioJwt = require('socketio-jwt');
var dotenv = require('dotenv').config({path:'../.env'});
var port = 3000;
io
.on('connection', socketioJwt.authorize({
secret: dotenv.JWT_SECRET,
timeout: 100 // 15 seconds to send the authentication message
}))
.on('authenticated', function(socket){
console.log('connected & authenticated: ' + JSON.stringify(socket.decoded_token));
socket.on('chat message', function(msg){
debugger;
io.emit('chat message', msg);
});
});
http.listen(port, function(){
console.log('listening on *:' + port);
});
You may have misunderstood how dotenv works, as you're trying to use it's return value.
Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.
From: dotenv github
Instead, it exports the variables stored in the file located at ../.env as environment variables, that become available as a part of process.env.
So instead of this:
var dotenv = require('dotenv').config({path:'../.env'});
socketioJwt.authorize({
secret: dotenv.JWT_SECRET,
timeout: 100
})
Do this
// do this near the entry point to your application!!
require('dotenv').config({path:'../.env'});
socketioJwt.authorize({
secret: process.env.JWT_SECRET,
timeout: 100
})
I've looked around and it seems as if all the ways to implement SSEs in Node.js are through more complex code, but it seems like there should be an easier way to send and receive SSEs. Are there any APIs or modules that make this simpler?
Here is an express server that sends one Server-Sent Event (SSE) per second, counting down from 10 to 0:
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/countdown', function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
})
countdown(res, 10)
})
function countdown(res, count) {
res.write("data: " + count + "\n\n")
if (count)
setTimeout(() => countdown(res, count-1), 1000)
else
res.end()
}
app.listen(3000, () => console.log('SSE app listening on port 3000!'))
Put the above code into a file (index.js) and run it: node index
Next, put the following HTML into a file (public/index.html):
<html>
<head>
<script>
if (!!window.EventSource) {
var source = new EventSource('/countdown')
source.addEventListener('message', function(e) {
document.getElementById('data').innerHTML = e.data
}, false)
source.addEventListener('open', function(e) {
document.getElementById('state').innerHTML = "Connected"
}, false)
source.addEventListener('error', function(e) {
const id_state = document.getElementById('state')
if (e.eventPhase == EventSource.CLOSED)
source.close()
if (e.target.readyState == EventSource.CLOSED) {
id_state.innerHTML = "Disconnected"
}
else if (e.target.readyState == EventSource.CONNECTING) {
id_state.innerHTML = "Connecting..."
}
}, false)
} else {
console.log("Your browser doesn't support SSE")
}
</script>
</head>
<body>
<h1>SSE: <span id="state"></span></h1>
<h3>Data: <span id="data"></span></h3>
</body>
</html>
In your browser, open localhost:3000 and watch the SSE countdown.
I'm adding a simple implementation of SSE here. It's just one Node.js file.
You can have a look at the result here: https://glossy-ox.glitch.me/
const http = require('http');
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
// Server-sent events endpoint
if (req.url === '/events') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
...(req.httpVersionMajor === 1 && { 'Connection': 'keep-alive' })
});
const refreshRate = 1000; // in milliseconds
return setInterval(() => {
const id = Date.now();
const data = `Hello World ${id}`;
const message =
`retry: ${refreshRate}\nid:${id}\ndata: ${data}\n\n`;
res.write(message);
}, refreshRate);
}
// Client side
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(`
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>SSE</title>
</head>
<body>
<pre id="log"></pre>
</body>
<script>
var eventSource = new EventSource('/events');
eventSource.onmessage = function(event) {
document.getElementById('log').innerHTML += event.data + '<br>';
};
</script>
</html>
`);
});
server.listen(port);
server.on('error', (err) => {
console.log(err);
process.exit(1);
});
server.on('listening', () => {
console.log(`Listening on port ${port}`);
});
If you're using express this is the easiest way https://www.npmjs.com/package/express-sse
on BE:
const SSE = require('express-sse');
const sse = new SSE();
...
app.get('/sse', sse.init);
...
sse.send('message', 'event-name');
on FE:
const EventSource = require('eventsource');
const es = new EventSource('http://localhost:3000/sse');
es.addEventListener('event-name', function (message) {
console.log('message:', message)
});
I found SSE implementation in node.js.
Github link: https://github.com/einaros/sse.js
NPM module:https://www.npmjs.com/package/sse
Will above link helps you ?
**client.js**
var eventSource = new EventSource("/route/events");
eventSource.addEventListner("ping", function(e){log(e.data)});
//if no events specified
eventSource.addEventListner("message", function(e){log(e.data)});
**server.js**
http.createServer((req, res)=>{
if(req.url.indexOf("/route/events")>=){
res.setHeader('Connection', 'keep-alive');
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Content-Type", "text/event-stream");
let event = "event: ping";
let id = `id: ${Date.now()}`;
let data = {
message:`hello #${new Date().toString()}`
}
data = "data: "+JSON.stringify(data);
res.end(`${event}\n${id}\n${data}\n\n`);
}
}).listen(PORT)
After looking at the other answers I finally got this working, but what I ended up having to do was a little different.
[package.json] Use express-sse:
The exact version of express-sse is very important. The latest tries to use res.flush(), but fails and crashes the http server.
"express-sse": "0.5.1",
[Terminal] Install express-sse:
npm install
[app.js] Use the router:
app.use(app.baseUri, require('./lib/server-sent-events').router);
[server-sent-events.js] Create sse library:
The call to pause() is the equivalent of flush(), which was removed from express. It ensures you'll keep getting messages as they are sent.
var express = require('express');
const SSE = require('express-sse');
const sse = new SSE();
var router = express.Router();
router.get('/sse', sse.init)
module.exports = {
send,
router
};
async function send(message) {
sse.send(message.toProperCase(), 'message');
await pause();
}
function pause() {
return new Promise((resolve, reject) => {
setImmediate(resolve)
})
}
[your-router.js] Use the sse library and call send:
var express = require('express');
var serverSentEvents = require('../lib/server-sent-events');
var router = express.Router();
router.get('/somepath', yourhandler);
module.exports = router;
async function yourhandler (req, res, next) {
await serverSentEvents.send('hello sse!'); // <<<<<
}
[your-client-side.js] Receive the sse updates:
I recommend you keep the event.data.replace(/"/g,'') because express-sse tacks on enclosing quotes and we don't want those.
const eventSource = new EventSource('http://yourserver/sse');
eventSource.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data.replace(/"/g,'') + '...';
};
You should be able to do such a thing using Socket.io. First, you will need to install it with npm install socket.io. From there, in your code you will want to have var io = require(socket.io);
You can see more in-depth examples given by Socket.IO
You could use something like this on the server:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('../..')(server);
var port = process.env.PORT || 3000;
server.listen(port, function () {
console.log('Server listening at port ' + port);
});
app.use(express.static(__dirname + '/public'));
io.on('connection', function (socket) {
socket.emit('EVENT_NAME', {data});
});
And something like this on the client:
<script src="socket_src_file_path_here"></script>
<script>
var socket = io('http://localhost');
socket.on('EVENT_NAME', function (data) {
console.log(data);
//Do whatever you want with the data on the client
});
</script>