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>
Related
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 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.
I'm trying to set up a node.js application that could receive connections and still be listening to port 9001 once a socket is ended. How can I do that? Here is my current code (it doesn't close after the socket.end(), but it won't accept any other connections) :
var net = require('net');
var mySocket;
var server = net.createServer(function(socket) {
mySocket = socket;
mySocket.on("connect", onConnect);
mySocket.on("data", onData);
});
function onConnect() {
console.log("Connected");
}
function onData(command) {
if (command == "exit") {
console.log("Exiting");
mySocket.end();
}
}
console.log("Waiting for incoming connections");
server.listen(9001);
I tried to add another server.listen(9001); after the socket.end();, but I get a : Error: listen EADDRINUSE message.
Also, will that code be able to receive several connections coming from different addresses at the same time, and handle them separately?
This is the full code. When executed, node.js receives 4 commands from the Flash application, and works properly (except that the onConnect() function seems never to be called), and the "exit;" command closes the socket properly, yet if I reload the Flash application, it doesn't connect to the server
var net = require('net');
const PACKET_SEPARATOR = 59 // ;
var connection_ack = false;
var counter = 0;
var server = net.createServer(function(socket) {
function onConnect() {
console.log("Connected to Flash");
}
function dataHandler(command) {
if (command[command.length - 1] != String.fromCharCode(PACKET_SEPARATOR) && connection_ack) {
console.log("SEP : " + PACKET_SEPARATOR + " - last : " + command[command.length - 1] + " - ack " + connection_ack);
console.log("CAUGHT EXCEPTION : WRONG PACKET FORMAT --- " + command + " --- " + command.length);
}
if (command == "exit;") {
console.log("Received exit request from " + socket.address().address + ":" + socket.address().port + " (" + socket.address().family + "). Ending connection...");
socket.end();
}
else if (command == "<policy-file-request/>\0") {
socket.write('<cross-domain-policy>\n<allow-access-from domain="*" to-ports="*" />\n</cross-domain-policy>\0', 'utf8');
console.log("Policy file sent to " + socket.address().address + ":" + socket.address().port);
player1.pxacceleration = 0;
player1.pyacceleration = 0;
connection_ack = true;
}
else {
console.log("Got data from " + socket.address().address + ":" + socket.address().port + " (" + socket.address().family + ")");
console.log("--> " + command);
counter++;
socket.write("Received " + counter + " commands;", 'utf8');
console.log("Sending : Received " + counter + " commands;");
}
}
function onData(d) {
var command = "";
for (i=0; i <= d.length - 1; i++) {
command += String.fromCharCode(d[i]);
if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {
dataHandler(command);
command = "";
}
}
}
socket.on("connect", onConnect);
socket.on("data", onData);
});
console.log("Ready. Waiting for incoming connections");
server.listen(9001);
server.listen(80); //TODO : Remove?
As jfriend00 said, using mySocket as a global is not recommended. Try the below instead.
var server = net.createServer(function(socket) {
function onData(command) {
if (command == "exit") {
console.log("Exiting");
socket.end();
}
}
socket.on("connect", onConnect);
socket.on("data", onData);
});
...
This eliminates the need for the global in the first place. This should also allow multiple sockets and prevent the original error. I think. I'm new here, so I guess we will see.
EDIT
Alright. I've been interacting with your code via telnet. I've also read up on some of the documentation. First, the socket.on("connect", onConnect); listener should be moved(along with the onConnect function) into the global scope and changed to server.on("connection", onConnect);. The reason for this is that the socket event listener connect is a client side listener. We are working server side. The server side listener for new connections is connection and the server should be listening for it in the same way it is listening for connections on a particular port.
This part of your code should look like this now:
//more code up above here
....
function onData(d) {
var command = "";
for (i=0; i <= d.length - 1; i++) {
command += String.fromCharCode(d[i]);
if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {
dataHandler(command);
command = "";
}
}
}
socket.on("data", onData);
});
function onConnect() {
console.log("Connected to Flash");
}
server.on("connection", onConnect);
....
//more code below here
However, the code would not recognize exit as a command via telnet. I was unable to figure this bit out. Since your question did not cover this problem it might just be me or you have it figured out.
EDIT 2
The code below keeps it local.
var server = net.createServer(function(socket) {
function onConnect() {
console.log("Connected to Flash");
socket.write("we're connected");
}
....
function onData(d) {
var command = "";
for (i=0; i <= d.length - 1; i++) {
command += String.fromCharCode(d[i]);
if (d[i] == PACKET_SEPARATOR || i == d.length - 1 && !connection_ack) {
dataHandler(command);
command = "";
}
}
}
onConnect();
socket.on("data", onData);
});
AS3 XMLSocket sends data from all clients started, but data recieved only by last client connected.
I have the flash web client, and if you open for example 2 or more tabs with the app, every client will send the data to socket server, but only THE LAST client connected gets all the data. Here is the link http://151.248.124.213/. It has chat alike interface for now and green button is the SEND button. App gets connected when you hit stage with the mouse. App is connected when the message Connected appears in the screen. To test http://151.248.124.213/ just open 2 or more tabs.
Here is the AS3 code:
Security.loadPolicyFile("xmlsocket://151.248.124.213:3843");
var socket:XMLSocket;
stage.addEventListener(MouseEvent.CLICK, doConnect);
function doConnect(evt:Event):void
{
stage.removeEventListener(MouseEvent.CLICK, doConnect);
socket = new XMLSocket("151.248.124.213", 3000);
socket.addEventListener(Event.CONNECT, onConnect);
socket.addEventListener(IOErrorEvent.IO_ERROR, onError);
}
function onConnect(evt:Event):void
{
trace("Connected");
output_txt.text = "Connected\n";
socket.removeEventListener(Event.CONNECT, onConnect);
socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);
socket.addEventListener(DataEvent.DATA, onDataReceived);
socket.addEventListener(Event.CLOSE, onSocketClose);
}
function onSocketClose(evt:Event):void
{
trace("Connection Closed");
socket.removeEventListener(Event.CLOSE, onSocketClose);
socket.removeEventListener(DataEvent.DATA, onDataReceived);
}
function onError(evt:IOErrorEvent):void
{
trace("Connect failed");
socket.removeEventListener(Event.CONNECT, onConnect);
socket.removeEventListener(IOErrorEvent.IO_ERROR, onError);
}
function onDataReceived(evt:DataEvent):void
{
try {
trace( "From Server:", evt.data );
var msg = evt.data;
output_txt.text += msg + "\n";
}
catch (e:Error) {
trace('error');
}
}
send_btn.addEventListener(MouseEvent.CLICK, send_btn_clicked);
function send_btn_clicked(evt:MouseEvent):void
{
var msg = input_txt.text;
socket.send(msg);
input_txt.text = "";
}
And here is the server code:
var express = require('express');
var app = express.createServer();
app.configure(function () {
app.use(express.static(__dirname));
})
app.listen(80);
var net = require('net');
var mySocket;
var server = net.createServer(function(socket) {
mySocket = socket;
mySocket.on("connect", onConnect);
mySocket.on("data", onData);
});
server.listen(3000);
function onConnect()
{
console.log("Connected to Flash");
}
function onData(d)
{
if(d == "exit\0")
{
console.log("exit");
mySocket.end();
server.close();
}
else
{
console.log("From Flash = " + d);
mySocket.write(d, 'utf8');
}
}
You have to create one socket per client on server side.
Each time a new client is connected, create a new socket. look here for an example.
I'm trying to use REPL over socket like a telnet connection, but when I press CTRL + C or CTRL + D, or an error is produced, the socket connection hangs and doesn't respond to anything.
The node.js code is:
var net = require("net");
var connections = 0;
// Socket port 5001
net.createServer(function (socket) {
connections += 1;
var server = require("repl").start(
'session:' + connections + ' > ',
socket
);
server.rli.on('exit', function() {
socket.end();
});
}).listen(5001);
// Console
var server = require("repl").start('session:' + (++connections) + ' > ', null);
and from other terminal I run:
telnet localhost 5001
What is the problem?
Perhaps is a linux problem.
I've tried a Telnet server example with node.
When I run on window, every key I press is processed by receiveData function, but in linux no.
In linux is processed line per line and not character per character.
Here is the code I've probed:
var net = require('net');
var sockets = [];
/*
* Cleans the input of carriage return, newline
*/
function cleanInput(data) {
return data.toString().replace(/(\r\n|\n|\r)/gm,"");
}
/*
* Method executed when data is received from a socket
*/
function receiveData(socket, data) {
var cleanData = cleanInput(data);
if(cleanData === "#quit") {
socket.end('Goodbye!\n');
}
else {
for(var i = 0; i<sockets.length; i++) {
if (sockets[i] !== socket) {
sockets[i].write(data);
}
}
}
socket.write('Data: ' + data);
}
/*
* Method executed when a socket ends
*/
function closeSocket(socket) {
var i = sockets.indexOf(socket);
if (i != -1) {
sockets.splice(i, 1);
}
}
/*
* Callback method executed when a new TCP socket is opened.
*/
function newSocket(socket) {
sockets.push(socket);
socket.write('Welcome to the Telnet server!\n');
socket.on('data', function(data) {
receiveData(socket, data);
})
socket.on('end', function() {
closeSocket(socket);
})
}
// Create a new server and provide a callback for when a connection occurs
var server = net.createServer(newSocket);
// Listen on port 8888
server.listen(8888);