I have 2 scripts in node js. One uses 'http' and other uses 'net'. I want to make these scripts together in one script. My 'http' script are as below:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
console.log(req.headers);
res.statusCode = 200;
res.end('<html><body><h1>Hello, World!</h1></body></html>');
})
server.listen(port, hostname);
'net' script:
var net = require('net');
var client = new net.Socket();
client.connect(4352, 'x.x.x.x', function() {
console.log('Connected');
client.write('%1POWR 1\r\n');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
My purpose is to run the 'net' script once I start the 'http' script.
Wrap the whole net script in a exported function:
var net = require('net');
module.exports = () => {
var client = new net.Socket();
client.connect(4352, 'x.x.x.x', function() {
console.log('Connected');
client.write('%1POWR 1\r\n');
});
client.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
client.on('close', function() {
console.log('Connection closed');
});
}
Import and execute the exported function in http script:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
require('path/to/net/script')() //Add to anywhere you like
const server = http.createServer((req, res) => {
console.log(req.headers);
res.statusCode = 200;
res.end('<html><body><h1>Hello, World!</h1></body></html>');
})
server.listen(port, hostname);
Related
I am trying to connect a backend layer running on localhost, below is the source code:
const { createServer } = require("http");
const cors = require("cors");
const photos = require("./photos");
const app = require("express")();
const WebSocket = require("ws");
app.use(cors());
app.get("/", (req, res) => {
res.status(200).json({});
});
app.get("/photos", (req, res) => {
res.status(200).json({ photos });
});
const clients = new Set();
app.post("/photos/:id", (req, res) => {
const photo = photos.find((p) => {
return p.id === req.params.id;
});
photo.status= "PENDING";
// Send back an approval
const timeout = (3 + Math.floor(Math.random() * 4)) * 1000;
setTimeout(() => {
photo.status = "APPROVED";
clients.forEach((ws) => {
ws.send(JSON.stringify({ event: "APPROVED", photo }));
});
}, timeout);
res.status(200).json({ photo });
});
const port = process.env.PORT || 3001;
const server = createServer(app);
server.listen(port, () => {
console.log(`Starting server on port ${port}`);
});
const wss = new WebSocket.Server({ path: "/ws", server });
wss.on("connection", (ws) => {
clients.add(ws);
console.log("WebSocket connection established");
ws.on("close", () => {
clients.delete(ws);
console.log("WebSocket connection closed");
});
});
As on react client we can't use "ws" so I tried using both "websocket" package but I am not able to connect to "http" as it is not supported. Below is the source code:
import React from "react";
import { w3cwebsocket as W3CWebSocket } from "websocket";
const client = new W3CWebSocket('http://localhost:3001/ws');
// const client = new W3CWebSocket('ws://localhost:3001');
function App() {
React.useEffect(
() => {
client.onopen = () => {
console.log('WebSocket Client Connected');
};
client.onmessage = (message) => {
console.log(message);
};
}, []
)
return null
}
Need help at client level to connect to 'http://localhost:3001/ws' to establish and listen connection.
You are connecting to the wrong url. In following line on the server, you specify a path as /ws .
const wss = new WebSocket.Server({ path: "/ws", server });
So you need to connect to the specified path.
const client = new W3CWebSocket('ws://localhost:3001/ws');
If you remove the path: "/ws" from your createServer, the url ws://localhost:3001 (notice, no /ws path.. )should also work as expected.
Here's an example which worked on my machine ( without react, it's for showing socket connection.)
Client
var W3CWebSocket = require('websocket').w3cwebsocket;
const client = new W3CWebSocket('ws://localhost:3001/ws');
client.onopen = () => {
console.log('WebSocket Client Connected');
};
client.onmessage = (message) => {
console.log(message);
};
client.onerror = function() {
console.log('Connection Error');
};
Server
const { createServer } = require("http");
const cors = require("cors");
const app = require("express")();
const WebSocket = require("ws");
app.use(cors());
const port = process.env.PORT || 3001;
const server = createServer(app);
server.listen(port, () => {
console.log(`Starting server on port ${port}`);
});
const wss = new WebSocket.Server({ path: "/ws", server });
wss.on("connection", (ws) => {
console.log("WebSocket connection established");
ws.on("close", () => {
console.log("WebSocket connection closed");
});
});
i had my app with http, but i want add https, but i don't know how enable https on socket.io. The problem when i replaced http in 'require('socket.io)(https ....)' socket.io launch 404 error.
const http = require('http').Server(app);
const io = require('socket.io')(http, { pingInterval: 2000, pingTimeout: 7000,});
var https = require('https');
var fs = require('fs');
io.on('connect', socket => {
socket.on('ask', function(msg) {
search
.query(msg, socket.user, socket.token)
.then(result => {
socket.emit('response', result);
})
.catch(err => {
console.log(err);
socket.emit('response', {
msg: { text: "Lo siento, no puedo entender eso " },
type: 'error',
});
});
});
skills.registerClient(socket, socket.user).catch(err => {
console.warn('Failed to register client', err);
});
});
const port = await global.db.getGlobalValue('port');
http.listen(port, () => {
console.log(`Server started on http://localhost:${port}`);
});
const sslPort = '1443';
const server = https.createServer(httpsOptions, app)
.listen(sslPort, () => {
console.log(`Https server on https://localhost:${sslPort}`);
});
I am Currently using this:
const fs = require('fs');
const options = {
rejectUnauthorized: true,
key: fs.readFileSync('<SSL KEY PATH>/privkey.pem'),
cert: fs.readFileSync('<SSL CERT PATH>/fullchain.pem')};
const app = require('https').createServer(options);
const io = require('socket.io')(app);
io.on('connection', socket => {
console.log("New Connection");
socket.on('ask', function(msg) {
//your code here
});
});
app.listen(<PORT>); //e. g. 8080, Integer
First, you need to create cert and key for ssl.
After key and cert are generated, you can code like the following:
const express = require('express')
const https = require('https')
const fs = require('fs')
const port = 8888
const cert = fs.readFileSync('/path/to/your_cert.cert')
const key = fs.readFileSync('/path/to/your_key.key')
const SSLOption = {
key, cert
}
app = express()
let server = https.createServer(SSLOption, app)
server.listen(port, () => {
console.log('server started on port: ' + port)
})
app.get('/', (req, res) => {
res.send('Working good...')
})
const io = require('socket.io')(server)
io.on('connection', (socket) => {
console.log(socket)
})
enter image description here
This is the error.
var httpsOptions = {
key: fs.readFileSync(path.join(__dirname + '/ssl/localhost-key.pem')),
cert: fs.readFileSync(path.join(__dirname + '/ssl/localhost.pem'))
};
This is my httpsOptions.
I have created communication between client and server using socket.io, Now I am sending commands from client to server using WebSockets, I would like to run these received commands from the client on the server
Here is my solution
HTML (client)
<html>
<body>
I am client
</body>
<script>
const ws = new WebSocket('ws://localhost:9898/');
ws.onopen = function() {
console.log('WebSocket Client Connected');
ws.send('npm run build');
};
ws.onmessage = function(e) {
console.log("Received: '" + e.data + "'");
};
</script>
</html>
Here is server.js
const http = require('http');
const WebSocketServer = require('websocket').server;
const server = http.createServer();
server.listen(9898);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message) {
console.log(message.utf8Data);
connection.sendUTF('Hi this is WebSocket server!');
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
Now when we run the server and open index.html, the server receives the following message
`npm run build`
Now how do I run this command on a server using a child process?
You can use child_process to spawn a new process for your server.js like below
const http = require('http');
const WebSocketServer = require('websocket').server;
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const server = http.createServer();
server.listen(9898);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message) {
console.log(message.utf8Data);
const { stdout, stderr } = await exec(message.utf8Data);
console.log('stdout:', stdout);
console.log('stderr:', stderr);
connection.sendUTF('Hi this is WebSocket server!');
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
I'm trying to serve multiple audio files in the node.js server, but the server sometimes fails when multiple clients try to access. How can I remedy this?
express = require('express');
const http = require('http');
const path = require('path');
const fs = require('fs');
const app = express();
app.get('/', function (request, response) {
let fpath = base_dir + filenames[getIndex(filenames.length)];
let filestream = fs.createReadStream(fpath);
var d = new Date();
filestream.on('open', function() {
let stats = fs.statSync(fpath);
let fileSizeInBytes = stats["size"];
response.writeHead(200, {
"Accept-Ranges": "bytes",
'Content-Type': 'audio/mpeg',
'Content-Length': fileSizeInBytes});
filestream.pipe(response);
});
})
app.listen(3000, function () {
console.log('Audio file provider listening on port 3000');
})
You're using fs.statSync() which will block the thread also listening for incoming connections. Instead you should switch to the asynchronous version fs.stat().
app.get('/', (req, res) => {
let fpath = base_dir + filenames[getIndex(filenames.length)]
let d = new Date()
fs.stat(fpath, (err, stats) => {
// Handle Error when trying to get file stats
// Respond with 500 Internal Server Error
if (err) {
console.log(err)
return res.sendStatus(500)
}
let {size} = stats
res.status(200)
res.setHeader('Accept-Ranges', 'bytes')
res.setHeader('Content-Type', 'audio/mpeg')
res.setHeader('Content-Length', size)
fs.createReadStream(fpath).pipe(res)
})
})
You're already using express, no need to reinvent the wheel http://expressjs.com/en/4x/api.html#res.sendFile
app.get('/', function (request, response) {
let fpath = base_dir + filenames[getIndex(filenames.length)];
response.sendFile(fpath, function(err) {
//Handle err if any
});
})
For example my idea is:
File1.js
io.sockets.on('connection', function (socket) {
socket.on('file1Event', function () {
//logic
});
});
File2.js
io.sockets.on('connection', function (socket) {
socket.on('file2Event', function () {
//logic
});
});
This code is for a node server, will I have problems with this code?
Nope, just use the same "io" object.
File1.js
exports = module.exports = function(io){
io.sockets.on('connection', function (socket) {
socket.on('file1Event', function () {
console.log('file1Event triggered');
});
});
}
File2.js
exports = module.exports = function(io){
io.sockets.on('connection', function (socket) {
socket.on('file2Event', function () {
console.log('file2Event triggered');
});
});
}
app.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, file1 = require('./File1')(io)
, file2 = require('./File2')(io)
app.listen(3000);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.emit('file1Event'); // 'file1Event triggered' will be shown
socket.emit('file2Event'); // 'file2Event triggered' will be shown
</script>
Be careful not to generate a new connection event for each file. You should use the same on('connection') event, otherwise after 10 files imported, you will get this error from node: MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connection listeners added. Use emitter.setMaxListeners() to increase limit.
The better way is to do like this in your main file:
io.on('connection', function (socket) {
require('pathToSocketRoutesFile1')(socket);
require('pathToSocketRoutesFile2')(socket);
require('pathToSocketRoutesFileN')(socket);
return io;
};
and in each separate file:
module.exports = function(socket) {
socket.on('eventName1', function() {
//...
});
socket.on('eventName2', function() {
//...
});
};
Another option is to create a rootSocket which handles the initial connection and then passes the socket to other handlers.
const rootSocket = (io) => {
io.sockets.on('connection', (socket) => {
authorization(socket);
chat(socket);
});
};
exports.default = rootSocket;
You Can use IO module in any route just create global middleware.
socketiomw.js
module.exports = (io)=>{
return (req,res,next)=>{
req.io = io;
next();
}
}
middlewares.js
module.exports.global = {
socketIo:require('./socketiomw'),
// add other global middleware
};
index.js
const express = require('express');
const app = express();
const port = 3000;
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
//global middleware initialization
app.use(require('./middlewares').global.socketIo(io));
app.get('/notify',(req,res)=>{
req.io.emit("hello");
req.io.to("someRoom").emit("some event");
req.io.to("room1").to("room2").to("room3").emit("some event");
req.io.of("/").adapter.on("create-room", (room) => {
console.log(`room ${room} was created`);
});
req.io.of("/").adapter.on("join-room", (room, id) => {
console.log(`socket ${id} has joined room ${room}`);
});
req.json({ success:true })
);
server.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
I used this in global middleware so i can use this io module in any routes
rootSocket.js :
const rootSocket = (io) => {
io.on('connection', (socket) => {
console.log('New connection');
// possibility to outsource events
socket.on('myEvent', () => {
console.log('myEvent triggered');
});
});
}
module.exports = rootSocket;
index.js :
const express = require('express');
const app = express();
//app.use(express.json());
//const cors = require('cors');
//app.use(cors());
const http = require('http');
const server = http.createServer(app);
const socketIo = require('socket.io');
const io = socketIo(server);
const rootSocket = require('./rootSocket')(io);
const port = 8000;
// process.env.PORT for production
server.listen(port, () => console.log('server started on ' + port));