I have successfully implemented the following nodejs websocket server on my local machine, however when attempting to move it to production I am unable to connect(not sure if the server code is needed but I will include anyway):
var ws = require("nodejs-websocket");
var server = ws.createServer(function(conn){
console.log("New connection");
//conn.sendText("You are connected");
conn.on("text", function(str){
//conn.sendText(str.toUpperCase() + "!!!");
var inputOBJ = JSON.parse(str);
if(inputOBJ.TYPE === 'USERNAME'){
conn.username = inputOBJ.BODY;
}
if(inputOBJ.TYPE === 'MESSAGE'){
//console.log("Connected User: " + conn.username);
//console.log("Recipient: " + inputOBJ.RECIPIENT);
//console.log("Body: " + inputOBJ.BODY);
var userOnline = false;
server.connections.forEach(function(connection){
if(connection.username === inputOBJ.RECIPIENT){
userOnline = true;
var message = {};
message.TYPE = "USER";
message.BODY = inputOBJ.BODY;
connection.sendText(JSON.stringify(message));
}
});
if(!userOnline){
var message = {};
message.TYPE = "SYSTEM";
message.BODY = "User is not online";
conn.sendText(JSON.stringify(message));
}
}
});
conn.on("close", function(code, reason){
//console.log("Connection closed");
});
conn.on('error', function(err){
//console.log(err.stack);
});
}).listen(1337);
When I run the program on my server it acts like it's running as if everything were alright. After checking the ports by running command netstat -lntu I can verify that the port is open. The following is the row showing port 1337:
tcp 0 0 0.0.0.0:1337 0.0.0.0:* LISTEN
If there is anything else I can provide please let me know. As of right now I'm not sure why it will not accept connections???
This turned out to be do to firewall rules set on the one of the networks I was testing from. When I connected from another network, everything functioned as expected.
Related
I am creating a TCP server to listen data from a IOT client in Electron.
In mac I get pop up about allowing incoming traffic in app but in windows nothing happens and windows does not allow incoming traffic when firewall is on.
but if I turn off the fire all app works fine. But I want app to work even if firewall is on
can anyone help so that I can add exception to firewall using nodeJS code in my electron app?
function startSocket() {
try {
dataServer = net.createServer();
dataServer.on("error", function (error) {
console.log(error);
showMsg(error.message, "red");
dataServer.close();
});
dataServer.on("connection", handleConnection);
dataServer.listen(port, function () {
const address = dataServer.address();
var privateIP = ip.address();
sendMessage({
title: "start",
frequencies: frequencies,
Ns: Ns,
count: frequencies.length,
ip: privateIP,
port: port,
singleChannel: singleChannel,
});
disableElements([startBtn]);
noLostPackets = 0;
console.log(`Listing for Data at ${privateIP}:${address.port}`);
showMsg(`Listing for Data at ${privateIP}:${address.port}`, "green");
});
function handleConnection(conn) {
let fullDataString = "";
var remoteAddress = conn.remoteAddress + ":" + conn.remotePort;
showMsg(`new client connection from ${remoteAddress}`);
conn.on("data", onConnData);
conn.on("end", onConnClose);
conn.on("error", onConnError);
function onConnData(data) {
fullDataString += data.toString();
//appending data to the file
showMsg(`Packet recived`);
conn.write("data recived");
}
function onConnClose() {
showMsg(`writing to file...`);
packet.classList.add("packet");
restartAnimation();
try {
data_obj = JSON.parse(fullDataString);
} catch (error) {
showMsg("Not Valid JSON data", "red");
console.log("Not Valid JSON data");
return;
}
let numberOfLines = data_obj.data.split(/\n/).length - 1;
writeToFile(
saveFilePath,
data_obj.data,
data_obj.frequency,
numberOfLines
);
noOfPackets += numberOfLines;
bigNumber.innerText = noOfPackets;
}
function onConnError(err) {
console.log(err);
showMsg(`Reconnecting...`, "green");
}
}
} catch (error) {
console.log(error);
showMsg(error.message, "red");
}
}
I have two servers one on port 80 which is a normal web server and than one on port 8080 that is a broadcast server that sends a text string with all the updates to show. However the browser gives me a CORS header 'Access-Control-Allow-Origin' missing. And is it any simple way for me to add the header with the net package? The server code looks as following:
Code to create the server:
var net = require('net');
var fs = require('fs');
var buffer = require('buffer');
var serverHost = "0.0.0.0";
var serverPort = 8080;
var splitter = require('./splitter.js');
var server = net.createServer(function(target) {
// Socket errors
target.on('error', function(error) {
console.log('Socket error: ', error.message);
});
target.on('data', function(data){
// TODO: Verify the data
var number = parseInt(data);
if(!isNaN(number)){
// Adds the client to the list
splitter.addClient(target, number);
}
else{
target.write("Match ID is not correctly formatted");
}
});
});
// Listening for any problems with the server
server.on('error', function(error) {
console.log("Error listening to the server!", error.message);
});
server.listen(serverPort, serverHost);
splitter code (Add client and send data):
var gameids = {1337:[]}
function addClient(client, gameID){
if(matchExists(gameID)){
console.log("Client", client.remoteAddress, "begun watching gameID", gameID,"\n");
var id = gameids[gameID].push(client);
}
else{
client.write("A match with the given ID does not exists");
}
}
function sendData(data, gameID){
if(gameids[gameID].length > 0){
for(i = 0; i < gameids[gameID].length;i++){
console.log(gameids[gameID][i]);
if(gameids[gameID][i].writable){
console.log("Sent data");
gameids[gameID][i].write(data);
}
}
}
}
The function send data is called from my main script which just takes the input from another server and then sends that out to all clients watching.
I'm brand new to node.js (or javascript in general) and not sure what's going on here. Sometimes when I run my node.js server, right when it starts up it begins printing data from the last time it ran. Is there something that could be keeping everything from resetting on a new run? I have arduino XBee nodes connecting to this server. Here's my node.js code:
var SerialPort = require("serialport");
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var ON_DEATH = require('death');
// Set up serial port
var portName = process.argv[2],
portConfig = {
baudRate: 9600,
parser: SerialPort.parsers.readline("\n")
};
var sp = new SerialPort(portName, portConfig); // got rid of deprecation issue with sp4
// Respond with file when a GET request is made to the homepage: app.METHOD(PATH, HANDLER) '/'=homepage
app.get('/', function(req, res){
res.sendfile('index.html');
});
// Listen on the connection event for incoming sockets, and log it to the console.
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
});
socket.on('chat message', function(msg){
io.emit('chat message', msg);
sp.write(msg + "\n");
});
});
// Make the http server listen on port 3000
http.listen(3000, function(){
console.log('listening on *:3000');
});
/////////////////////////////////////////////////////////////////////////////////////////////////
sp.on("open", function (err) {
if (err)
return console.log('Error opening port: ', err.message);
console.log('open');
// INFO VARIABLES
//var nodeCount = 0;
var pendingNodes = [];
var connectedNodes = [];
var buffer0;
var nodeInfo;
// Cleanup when termination signals are sent to process
ON_DEATH(function(signal, err) {
var death_msg = "Q";
sp.write(death_msg);
sp.close();
// zero out all variables
pendingNodes = [];
connectedNodes = [];
buffer0 = [];
nodeInfo = [];
console.log("\n\nSending reset signal to nodes.\n\n")
sp.flush(function(err,results){});
process.exit();
})
// listen for data, grab time, delimit
sp.on('data', function(data) {
var time = new Date();
buffer0 = data.split('\n'); // array of data till newline
// Split again into either "#ID" into [#ID] (if new broadcast), or "#ID Data" into [#ID, Data] (preconnected node)
nodeInfo = buffer0[0].split(' ');
//console.log(" nodeInfo: " + nodeInfo);
// DEBUGGING PRINT -- DELETE LATER
//console.log(" pendingNodes: " + pendingNodes + " connectedNodes: " + connectedNodes);
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Receiving ID or [ID, Data] -- Testing all possible cases
// if first char
if (nodeInfo[0][0] == "#") { // could check up here for && no temp data too
// Brand new node (ID not in pendingNodes or connectedNodes)
if ((pendingNodes.indexOf(nodeInfo[0]) == -1) && (connectedNodes.indexOf(nodeInfo[0]) == -1)) {
console.log("Brand new node: " + nodeInfo[0])
pendingNodes.push(nodeInfo[0]);
}
// Pending node (ID in pendingNodes, but not in connectedNodes)
else if ((pendingNodes.indexOf(nodeInfo[0]) != -1) && ((connectedNodes.indexOf(nodeInfo[0]) == -1))) {
console.log(" Pending node: " + nodeInfo[0])
// send back ID to confirm handshake
sp.write(nodeInfo[0]);
// Remove from pendingNodes
var index = pendingNodes.indexOf(nodeInfo[0]);
if (index > -1) {
pendingNodes.splice(index, 1);
}
// Add to connectedNodes
//var
connectedNodes.push(nodeInfo[0]);
}
// Connected node (ID in connectedNodes, but not in pendingNodes)
else if ((pendingNodes.indexOf(nodeInfo[0]) == -1) && (connectedNodes.indexOf(nodeInfo[0]) != -1)) {
console.log(" Connected node: " + nodeInfo[0] + " " + nodeInfo[1]);
// Disconnect nodes with undefined temperatures to force restart
if (typeof nodeInfo[1] == 'undefined') {
console.log("Undefined data for node: " + nodeInfo[0] + ". Dropping connection to this node.");
var index = connectedNodes.indexOf(nodeInfo[0]);
if (index > -1) {
connectedNodes.splice(index, 1);
}
}
//var t = time.getTime();
// FIRST: fix bug -- sometimes temp showing as undefined
// Then:
// Update data properly
// Average data
// add 3rd element to nodes for time stamp, check that all timestamps are recent periodically
// Detect drop-offs and remove nodes
}
// Error (ID in both pendingNodes and connectedNodes [should not happen])
else {
console.log("Error: node exists in both pending and connected.")
}
}
else if (nodeInfo[0][0] != "#") {
// FOR DEBUGGING PURPOSES, DELETE LATER
console.log("Error 2: incoming data does not start with '#'.")
}
/* // placeholders for functionality to add
var CalcAverage = function() {
console.log("CalcAverage: * every 1 second(s) *");
}
setInterval(function(){ CalcAverage() },2000);
var CheckNodes = function() {
console.log("CheckNodes: * every 6 second(s) *");
}
setInterval(function(){ CheckNodes() },6000);
*/
}); // end data
}); // end open
And here's an example of old node data showing up somehow:
Some possibilities:
Old (or new data that you didn't know it sent) data from clients has been buffered somehow on the serial port, or socket.io auto-reconnects on the client browsers and starts sending data even though you didn't interact with the client browser web page.
I have a multiplayer game where my server uses nodejs and TCPSocket (net.createServer) to communicate with a client.
I have thousands of clients connecting to the server and many people are complaining that they are constantly being disconnected from the server.
Here is how my server handles the connections now:
Init:
var net = require("net");
server = net.createServer(function(socket) {
socket.setTimeout(15000);
socket.setKeepAlive(true);
socket.myBuffer = "";
socket.msgsQue = [];
socket.on("data", onData);
socket.on("error", onError);
socket.on("end", onClientDisconnect);
socket.on("timeout", onClientDisconnect);
});
server.listen(port);
Sending to client:
var stringData = JSON.stringify({name:event, message:data});
if (!this.socket.msgsQue || typeof this.socket.msgsQue == "undefined")
this.socket.msgsQue = [];
this.socket.msgsQue.unshift(stringData);
var i = this.socket.msgsQue.length;
while(i--) {
if (this.socket.writable) {
var elem = this.socket.msgsQue[i];
this.socket.write(elem+"\0");
this.socket.msgsQue.splice(i, 1);
} else {
//Unable to write at index "i"
break;//will send the rest on the next attempt
}
}
When disconnected
var onClientDisconnect = function() {
this.myBuffer = "";
delete this.myBuffer;
this.msgsQue = [];
delete this.msgsQue;
this.destroy();
}
Receiving from client
var onData = function(data) {
if (!data || !data.toString()) return;
var raw = data.toString();
this.myBuffer += raw;
var d_index = this.myBuffer.indexOf('\0'); // Find the delimiter
// While loop to keep going until no delimiter can be found
var string;
while (d_index > -1) {
// Create string up until the delimiter
string = this.myBuffer.substring(0,d_index);
// Cuts off the processed chunk
this.myBuffer = this.myBuffer.substring(d_index+1);
onMessage(string, this);//handle
// Find the new delimiter
d_index = this.myBuffer.indexOf('\0');
}
}
A problem I notice is that msgsQue becomes huge because the socket is not writable, but disconnect handler is not fired (or hired later..)
Can you give me some advises on how to optimize this ?
I noticed that sometimes I get disconnected, but I can ping the server, so it is definitely a server-related problem. Can it be because of high load on the server itself?
(I do not want to use socket.io because the last year I had many problems with it like memory leaking, freezing the server app, no support, etc..)
I have a working node.js server when it runs on localhost, i can send and receive data from my client (written in java). However, when i move the server.js to the VPS application at Openshift (free) the client can no longer connect to the server.js.
I've uploaded the files as instructed, I open a SSH connection via terminal to server, navigate to the repo folder (where uploaded files is), run "node server.js" (it appears to be online, no error and the on.('online',..) events activates.
And when i then run the client on my computer it isn't able to connect to the server.js.
server.js:
var os = require('os');
var HOST = process.env.OPENSHIFT_NODEJS_IP;;
var PORT = process.env.PORT || 80;
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
var net = require('net');
console.log("Hostname: " + HOST + "\nPort: " + PORT);
if (cluster.isMaster) {
cluster.SCHED_RR;
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
Object.keys(cluster.workers).forEach(function(id){
console.log("I am runnong with ID: " + cluster.workers[id].process.pid);
});
console.log('\n');
cluster.on('online', function(worker) {
console.log('Worker: ' + worker.process.pid + " listning on port " + PORT);
});
cluster.on('exit', function(worker, code, signal){
console.log("Worker " + worker.process.pid + " died")
});
} else {
// Load the TCP Library
net = require('net');
// Keep track of the chat clients
var clients = [];
// Start a TCP Server
var server = net.createServer(function (socket) {
console.log('\n');
// Identify this client
socket.name = socket.remoteAddress + ":" + socket.remotePort
// Put this new client in the list
clients.push(socket);
// Send a nice welcome message and announce
socket.write("Welcome " + socket.name + "\n\n");
broadcast(socket.name + " joined the chat\n", socket);
// Handle incoming messages from clients.
socket.on('data', function (data) {
//var ls = net.connect(5001, 'localhost');
var string = data + "";
//console.log(string);
var message = string.split("|");
broadcast(" Passing data from "+message[2]+" to "+message[1] + "\n " + message[3], socket);
//ls.write(string);
//ls.end();
});
socket.on('connect', function(){
broadcast("\n New connection opened.\n");
});
// Remove the client from the list when it leaves
socket.on('end', function () {
clients.splice(clients.indexOf(socket), 1);
broadcast("\n" + socket.name + " left the chat.\n");
});
// Send a message to all clients
function broadcast(message, sender) {
clients.forEach(function (client) {
// Don't want to send it to sender
if (client === sender) return;
client.write(message);
});
// Log it to the server output too
process.stdout.write(message)
}
})
server.listen(PORT, HOST);
server.on('error', function (e) {
if (e.code == 'EADDRINUSE') {
console.log('Address in use, retrying...');
setTimeout(function () {
server.close();
server.listen(PORT, HOST);
}, 1000);
}
else if (e.code == 'ECONNREFUSED') {
console.log('Connection refused');
}
});
}
Client.java (relevant parts)
public static void main(String args[]) {
String s = getPackage();
try {
System.out.print("\n");
/*InetAddress addr;
Socket sock = new Socket("ex-std-node272.prod.rhcloud.com", 80);
addr = sock.getInetAddress();
System.out.println("Connected to " + addr);*/
Socket skt = new Socket("127.10.100.1", 80);
BufferedReader inStream = new BufferedReader(new
InputStreamReader(skt.getInputStream()));
DataOutputStream outStream = new DataOutputStream(skt.getOutputStream());
//System.out.print(" Received string: '");
//while (!inStream.ready()) {}
//System.out.print(inStream.readLine()); // Read one line and output it
System.out.print("'\n\n");
// Send first message
//outStream.writeByte(1);
outStream.writeUTF(s);
//outStream.flush(); // Send off the data
//outStream.write(b,0,b.length);
outStream.flush(); // Send off the data
}
catch(Exception e) {
System.out.print(" Error: " + e);
}
}
When i run the server.js (at the VPS) it gives me the Hostname: 127.10.100.1 and Port: 80 which i've then pasted into the client.
So, what do i need to do with the code i have to make it connect?
You need to listen on port 8080, not port 80. Try reading over this section of the Developer Center on Port Binding: https://developers.openshift.com/en/managing-port-binding-routing.html
The first thing to note is that PORT in your server.js should be made equal to process.env.OPENSHIFT_NODEJS_PORT or 8080 as Corey already mentioned.
The second problem is that when you run your client on your local machine, the host you should be connecting to the URL given to your application when you created it something like http://<appname>-<domain>.rhcloud.com. You can see your application url when you issue the command:
rhc show-app <appname>