Node.js Server crashed when Refresh Browser - javascript

I tried to build a chat box server by node.js. When the browser requestes the page, it workes well at first. But when I refresh the page, the Server crashes.
Below is the error message:
events.js:183
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at _errnoException (util.js:1022:11)
at TCP.onread (net.js:615:25)
I used the node --inspect index.js, but could not find the point.
Below is the code of index.js:
const http = require('http');
const fs = require('fs');
const extract = require('./extract');
const wss = require('./websockets-server');
var handleError = function (err,res) {
res.writeHead(404);
res.end();
}
var server = http.createServer(function (req, res) {
console.log("Responding to a request.");
var filePath = extract(req.url);
console.log("filePath:"+filePath);
fs.readFile(filePath,function (err,data) {
if(err){
handleError(err,res);
return;
}else {
res.end(data);
}
})
})
server.listen(3000);
When I comment the 4th line, the import of websockets-server. Server works well when I refresh the page. Maybe it's about the websocket while it works without websocket.
Below is code of websockets-server.js:
const WebSocket = require('ws');
var WebSocketServer = WebSocket.Server;
var port = 3001;
var ws = new WebSocketServer({
port:port
});
var message = [];
console.log('websockets server started');
ws.on('connection', function (socket) {
console.log('client connection established');
message.forEach(function (msg) {
socket.send(msg);
})
socket.on('message', function (data) {
console.log('message received: ' + data);
message.push(data);
ws.clients.forEach(function (clientSocket) {
clientSocket.send(data);
});
});
});
Does the problem is about the websocket? Whether should I do process when the client shutdown the connection with the server while refreshing the page.
extract.js below:
const path = require('path');
var extractFilePath = function (url) {
var filePath;
var fileName = 'index.html';
if(url.length > 1){
fileName = url.substring(1);
}
console.log('The fileName is: ' + fileName);
filePath = path.resolve(__dirname, 'app', fileName);
return filePath;
}
module.exports = extractFilePath;

I guess that you maybe execute var ws = new WebSocket("ws://localhost:3001"); in html file. I haven't figured out exact reason about your error as I'm not proficient in WebSocket. But there is a solution:
window.onbeforeunload = function () {
ws.close();
}
close connection before reload, then the error will not reappear.

You need to add an error listener on the socket. Error listener only on the websocket instance does not help in this case.
socket.on('error', function(e){
console.log(e);
});

The ECONNRESET error means that the other side (browser) closed the connection abruptly. On browser refresh, browser simple killed the connection with the websocket server.
To solve this, you have to listen for the error event on the websocket server instance.
// listen for "error" event so that the whole app doesn't crash
wss.on("error", function(error){
console.log(error);
}

I was having the same problem, but it resolved after this command:
npm install #ionic/app-scripts#nightly --save-dev

Related

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.

Nodejs proxy server Cannot set headers after they are sent to the client

I am trying to build a Nodejs server that takes data from another server that contain the data then send it to the client, I am using a proxy structure to handle multiple types of connection.
I am using an HTTP Express server to handle HTTP request and it works fine for the first request after the first request I have an Express error Cannot set headers after they are sent to the
client
_http_outgoing.js:526
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the
client
at ServerResponse.setHeader (_http_outgoing.js:526:11)
at ServerResponse.header (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (E:\Web\Projects\Color\server\node_modules\express\lib\response.js:170:12)
at EventEmitter.<anonymous> (E:\Web\Projects\Color\server\server.js:35:13)
at EventEmitter.emit (events.js:323:22)
at Socket.<anonymous> (E:\Web\Projects\Color\server\server.js:30:22)
at Socket.emit (events.js:323:22)
at addChunk (_stream_readable.js:294:12)
at readableAddChunk (_stream_readable.js:275:11)
at Socket.Readable.push (_stream_readable.js:209:10) {
code: 'ERR_HTTP_HEADERS_SENT'
}
My Express server code:
const express = require("express");
const net = require("net");
const http = require("http");
const login = require("./routes/auth");
const auth = require("./middlewares/verfication");
const info = require("./routes/info");
const events = require("events");
const eventEminter = new events.EventEmitter();
const app = express();
let clientSocket;
app.setClientSocket = (socket) => {
clientSocket = socket;
return true;
};
app.use(express.json());
app.use("/login", login);
app.use("/info", auth, info);
app.get("/", (req, res) => {
let clientData;
console.log("request has been made");
clientSocket.write("GET:/");
clientSocket.on("data", (data) => {
clientData = data.toString();
eventEminter.emit("ed");
console.log(clientData);
});
eventEminter.on("ed", () => {
res.send(clientData);
});
});
module.exports = app;
The clientSocket variable represents the connection with the data server .
Finally here is my server code:
const net = require("net");
const httpServer = require("./server");
//const clientServer = require("./client");
const dotenv = require("dotenv");
dotenv.config();
let clientSocket;
let registeredClient = false;
const proxyServer = net.createServer((socket) => {
socket.on("data", (data) => {
if (!data) {
socket.write("Error in request");
throw new Error("Request message is empty");
}
let request;
try {
request = data.toString();
} catch (error) {
console.log(
new Error("Request message can not be conveted to String")
);
throw error;
}
if (request.includes("HTTP")) {
const httpSocket = new net.Socket();
if (!registeredClient) {
registeredClient = httpServer.setClientSocket(clientSocket);
console.log("Client registered");
}
httpSocket.connect(4444, () => {
console.log("Proxy Connected to http server");
});
httpSocket.on("error", (err) => {
console.error("Proxy error: Could not connect to http server");
throw err;
});
const flushed = httpSocket.write(data, (err) => {
if (err) {
console.error(
"Proxy error :Could not send data to http server"
);
throw err;
}
});
// if (flushed) httpSocket.end();
let response;
httpSocket.on("data", (httpData) => {
if (!httpData) {
console.error(
"Proxy error: unable to retrive data from http server"
);
return;
}
socket.write(httpData.toString());
});
// httpSocket.on("end", () => {
// if (!response) {
// console.error(
// "Proxy error: unable to send response or empty response message"
// );
// return;
// }
// socket.write(response);
// });
} else {
if (!clientSocket) clientSocket = socket;
}
});
socket.on("error", (err) => {
console.error("Proxy error: could not connect with client");
});
});
const port = process.env.PORT || 4000;
proxyServer.listen(port, () => {
console.log(`Proxy Server is running on port ${port}`);
});
httpServer.listen(4444, () => {
console.log("Http server is running on port 4444");
});
thank you for helping.
You are calling res.send() on every "ed" event and you're emitting an "ed" event on every clientSocket.on('data', ...) event. So, as soon as you get a second data event you'll be trying to call res.send() for the second time on the same response. You only get one response per http request. You can't call res.send() more than once for a given http response.
It's unclear how this code is supposed to work since I don't know what you're really trying accomplish here. Perhaps you need to accumulate all the data from the data events and then send one response and then unhook all the listeners do you don't get any more data events for this request. Or, if you want to send the response on the first data event, then just unhook the data and ed listeners after you send the response.
Keep in mind that on a regular socket, you have no control over what data comes in a data event. TCP is a stream protocol and data can come in any size chunks and the chunks it arrives in may not be the exact same as the chunks it was sent in. You would typically have to be looking for some sort of complete packet yourself and be able to assemble or split data events into full packets you can do something with.
Generally this error "Cannot set headers after they are sent to the client" occurs when you are sending multiple response to the server. In your case,
eventEminter.on("ed", () => {
res.send(clientData);
});
As you are using this, you are sending multiple response to server. You should send the response only once. You can use this code instead
eventEminter.once('ed', () => {
res.send(clientData);
});

WebSocket stops working in Vue/Node application

I have a Node/Vue application. I am consuming a WebSocket from Binance, a crypto exchange. I can see the quotes on the server console as I log them, I can send them to the browser for a short period of time before the client stops logging them.
Browser just using WebSocket API
Node using ws library
Node code, this I am running as it's own service as its just this.
'use strict';
const WebSocket = require('ws');
const binanceWS = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt#trade')
const server = new WebSocket.Server({ port: 5002 });
//websocket connection event will return a socket you can later use
binanceWS.on("open", function() {
console.log("connected to Binance");
});
binanceWS.on('message', function(data){
console.log(data);
server.on('connection', function connection(ws){
console.log("Connected a new client");
ws.send(data);
});
server.on('closed', function (id){
console.log("connection closed");
console.log(id);
});
server.on('error', function (err){
console.log(err)
})
})
On the Client side I am using Vue and in the app.js file I have this on the created hook.
let socket = new WebSocket("ws://localhost:5002")
socket.addEventListener('message', function(event){
let quotes = JSON.parse(event.data);
console.log(quotes.p)
});
socket.addEventListener('error', function(event){
console.log("closing because " + event);
})
Right now I am only listening to the consoles in the above app.vue file.
What I see in the browser console is a lot of quotes, then they stop after a second or 2. There can be over a thousand quotes in some times. Then on occasion I see a console.log('created') that I have in a child component of app.vue. In many cases this is the last thing in the console after hundreds of quotes.
In the console.log for the server I see a lot of sessions being created with one page refresh. So much that it fills my console.
So I'm not sure I am creating the connections correcly, I am not sure if Vue is somehow stopping the console.log's?
I don't see any errors anywhere and the entire time in my server console the Binance API continues streaming.
you have to write server event listener outside binance on message handler;
then you can pass messages from binance to the server by emitting new event to the server
on receiving message from binance you can send data to all connection on the server
Or Try this code I think it will work :
'use strict';
const WebSocket = require('ws');
const binanceWS = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt#trade')
const server = new WebSocket.Server({ port: 5002 });
server.on('connection', function connection(ws){
console.log("Connected a new client");
});
server.on('closed', function (id){
console.log("connection closed");
console.log(id);
});
server.on('error', function (err){
console.log(err)
})
//websocket connection event will return a socket you can later use
binanceWS.on("open", function() {
console.log("connected to Binance");
});
binanceWS.on('message', function(data){
console.log(data);
server.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
})

socket.io not sending to client

I am trying to create a simple script to send data from a file every to the client every time the file is updated. I have tested and found that the file is read, but the client doesn't receive anything. there are no errors in the console. I am fairly new to socket.io.
node.js code
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require("fs");
var port = process.env.PORT || 3000;
app.get('/', function(req, res){
res.sendFile(__dirname + '/popup.html');
});
fs.watchFile("assets/popup.json", {interval:100}, function(curr, prev)
{
fs.readFile("assets/popup.json",{encoding:"utf8"}, function(err, data){
io.emit("popup", data)
})
});
http.listen(port, function(){
console.log('listening on *:' + port);
});
client code
var socket = io();
socket.on('popup', function(msg){
alert("hello")
});
Whenever things aren't working right like this, you need to resort to "debug mode". In that mode, you need to gather all possible events that might be happening and see what you learn from that. To that end, add this code to the client:
var socket = io();
socket.on('popup', function(msg){
console.log("hello: ", msg)
});
socket.on('connection', function() {
console.log("client connected");
});
socket.on('connect_error', function(err) {
console.log("client connect_error: ", err);
});
socket.on('connect_timeout', function(err) {
console.log("client connect_timeout: ", err);
});
These messages are all documented in the client-side doc on the socket.io Github site which you can find by Googling "socket.io github" at any time.
Then, see what you see in the browser console when the page loads. If you don't know how to open the browser console in whichever browser you are using, google it to find out. You need to be looking at the debug console when the page loads.
FYI, we're assuming that you've loaded socket.io into the page via a script tag before this code. If not, that error will show in the console too.
The OP then gets this error:
client connect_error:
Error: server error at Socket.onPacket (socket.io-1.2.0.js:1)
at XHR.<anonymous> (socket.io-1.2.0.js:1)
at XHR.Emitter.emit (socket.io-1.2.0.js:1)
at XHR.Transport.onPacket (socket.io-1.2.0.js:1)
at callback (socket.io-1.2.0.js:2)
at Object.exports.decodePayload (socket.io-1.2.0.js:2)
at XHR.Polling.onData (socket.io-1.2.0.js:2)
at Request.<anonymous> (socket.io-1.2.0.js:2)
at Request.Emitter.emit (socket.io-1.2.0.js:1)
at Request.onData (socket.io-1.2.0.js:2)
OK, progress. How are you loading socket.io in the client page? This seems like it might be that you have mismatched versions of socket.io in client and server. You should be doing:
<script src="/socket.io/socket.io.js"></script>
and then your server will be feeding the client page the exact same version of socket.io. Also, since this error reports client-side socket.io 1.2.0, what version of socket.io is installed on the server?
try this
socket.on('popup', function(msg){
socket.emit('message',"popup");
});
The issue appears to be you don't actually connect to a local socket.io server. By running node server.js with the code below you can start a web server. Then navigate to localhost in your browser to see the changes in console made to popup.json.
server.js
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
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);
});
}
fs.watchFile("popup.json", {interval: 100}, function (curr, prev) {
fs.readFile("popup.json", {encoding: "utf8"}, function (err, data) {
io.emit("popup", JSON.parse(data));
})
});
index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.on('popup', function (data) {
console.log(data);
});
</script>

Node.JS Only works on Localhost?

var app = require('http').createServer(handler);
var Rcon = require('rcon');
var url = require('url');
app.listen(7777);
console.log('Server started.');
function handler (req, res) {
console.log('New connection!');
res.writeHead(200);
var urlParts = url.parse(req.url, true);
var server = urlParts.query;
var conn = new Rcon(server.ip, server.port, server.password);
conn.on('auth', function() {
conn.send(server.command);
console.log('Sent command!');
}).on('response', function(data) {
res.end(data);
console.log('Response: '+data);
}).on('error', function(data) {
res.end('error');
console.log('Error: '+data);
}).on('err', function(data) {
res.end('error');
console.log('Error: '+data);
});
conn.connect();
}
All of that works perfectly on localhost but when I upload to a remote server and run it, it responds with error in browser and with this in the console:
Server started. New connection! Error: TypeError: Object 0�P�q has no
method 'writeInt32LE' New connection! Error: Error: EINVAL, Invalid
argument
First guess: rcon module contains compiled extensions and you checked the files of node_modules/rcon into git and then tried to run them on a different CPU architecture. You need to run npm rebuild on the remote server for a quick fix and to get your node_modules folder out of your git repository as the correct long-term fix.

Categories

Resources