Node JS Executed function twice [duplicate] - node.js

This question already has answers here:
nodejs - http.createServer seems to call twice
(3 answers)
Closed 9 years ago.
New at stackoverflow and new with Node.
I have one simple socket server and one web server.
I want the web server to send a message to the socket server if someone connected the web server.
Browser <=> Web Server/Socket Client <=> Socket Server
I created the server like this :
var http = require('http');
var net = require('net');
var HOST = '192.168.1.254';
var PORT = 8888;
var client = new net.Socket();
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n', function(){
client.connect(PORT, HOST, function() {
console.log('Connected To: ' + HOST + ':' + PORT);
client.write('0109001' + "\n");
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
console.log('The Data: ' + data);
client.destroy();
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
This code works but the web server sending the message to the socket server twice.
Did I do something wrong maybe with the callback or something?
Any help would be appreciated.

If you call this code by a browser it sends 2 requests to the server. One for the FavIcon and one for the page itself.
The code inside the callback is called twice because there are 2 requests.
As Matt mentioned: dont put the socket response handlers inside the callback, because you loose the reference to them and a new handler is attached for every request.
var http = require('http');
var net = require('net');
var HOST = '192.168.1.254';
var PORT = 8888;
var client = new net.Socket();
var url = require('url');
http.createServer(function (req, res) {
console.log(url.parse(req.url));
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n', function(){
console.log('Connected To: ' + HOST + ':' + PORT);
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

The client.on() calls shouldn't be inside the res.end() callback - that's causing the event handler to be attached multiple times, meaning that every time data is received, it's getting called multiple times.
Try this instead:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n', function(){
client.connect(PORT, HOST, function() {
console.log('Connected To: ' + HOST + ':' + PORT);
client.write('0109001' + "\n");
});
});
}).listen(1337, '127.0.0.1');
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
console.log('The Data: ' + data);
client.destroy();
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});

Related

Tunnel between servers that supports any port

I'm trying to create a tunnel using Node.js that will allow me to access Server X from Server Y. Server X is connected to a router that isn't port forwarded and I won't know the IP of Server X until it connects, which means that Server X has to open a socket to Server Y and not the other way round.
I've successfully created a version of this using socket.io. Server X opens a socket to server Y, the user can then access Server Y in a web browser and Server Y proxies the requests down the socket to Server X.
What I would like to do is allow access to any kind of port on Server X, and forward not just web requests but requests of any kind. For example, I'd like to allow forwarding of SSH so I can access SSH on Server X through Server Y (doesn't have to be port 22). localtunnel.me is an existing service which is an exact example of what I want to achieve.
Are there any libraries that could help me achieve this, or can I build it from the ground up quite easily? I built the web request tunnel easily, perhaps it can be adapted to support not just web traffic? I've attached the code to my existing web tunnel below.
Server X (connects to Server Y on port 3001, receives requests for data and sends it back:
var socket = require('socket.io-client')('http://localhost:3001');
socket.on('connect', function(){
console.log('Connected');
// Register the event for request of data
socket.on('request', function(data){
// Get the path
var options = {
host: 'localhost',
port: 3000,
path: data.path,
method: data.method
};
var request = http.get(options, function(resp){
resp.on('data', function(chunk){
socket.emit('response', { html: chunk });
// Probably need to fix this for file transfers. Use resp.on('end'
});
}).on("error", function(e){
console.log("Got error: " + e.message);
});
//Write our post data to the request
request.write(data.data);
//End the request.
request.end();
});
socket.on('disconnect', function(){});
});
Server Y (listens on port 3001 to connect to Server X, and listens on port 3002 for requests from user in web browser to forward to Server X:
app.listen(3001);
var rwPortalSocket;
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);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
// Save the socket object
rwPortalSocket = socket;
});
console.log('Data channel server running at http://127.0.0.1:3001/');
// Create web server
var http = require('http');
var qs = require('querystring');
http.createServer(function (req, res) {
// Send a request
rwPortalSocket.emit('request', { path: req.url, method: req.method });
// When we get a response
rwPortalSocket.on('response', function (responseData) {
res.writeHead(200);
res.end(responseData.html);
});
}).listen(3002, '127.0.0.1');
console.log('Web server running at http://127.0.0.1:3002/');
EDIT
I've now updated my code so that should support any TCP port or packet type. The code works fine when I tell net.connect to connect to a web server, but when I tell it to connect an SSH server, my SSH client complains with Protocol error: expected packet type 31, got 20
I've added an example of my new code connecting to an SSH server below.
Server X (connects to Server Y on port 3001, receives requests for data and sends it back:
var socket = require('socket.io-client')('http://localhost:3001');
socket.on('connect', function(){
console.log('Connected');
// Connect to 22
var buff = "";
var connected = false;
var net = require('net');
var client = net.connect({host: 'myserver.com', port: 22}, function() { //'connect' listener
connected = true;
console.log('Connected to 22');
});
// Register the event for request of data
socket.on('request', function(data){
if (!connected)
{
client = net.connect({host: 'myserver.com', port: 22}, function() { //'connect' listener
connected = true;
console.log('Connected to 22');
client.write(data.data);
});
}
else
{
client.write(data.data);
}
client.setMaxListeners(0);
// When data comes back to this service, we send it on to the other server
client.on('data', function(data) {
//console.log(data.toString());
console.log('Server sent back: ' + data.toString());
if (connected)
{
socket.emit('response', { data: data });
} else {
buff += d.toString();
}
});
client.on('end', function() {
console.log('Disconnected from 22');
connected = false;
});
client.on('error', function(e) {
console.log(e);
});
console.log('Client sent: ' + data.data);
});
socket.on('disconnect', function(){});
});
Server Y (listens on port 3001 to connect to Server X, and listens on port 3002 for requests from user in SSH Client (terminal) to forward to Server X:
app.listen(3001);
var rwPortalSocket;
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);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
// Save the socket object
rwPortalSocket = socket;
});
console.log('Data channel server running at http://127.0.0.1:3001/');
// Listen for tunnel requests
net = require('net');
var server = net.createServer(function(s) { //'connection' listener
s.on('end', function() {
console.log('server disconnected');
});
s.on('data', function (d) {
rwPortalSocket.emit('request', { data: d });
});
s.on('error', function(e) {
console.log(e);
});
s.setMaxListeners(0);
// When we get a response
rwPortalSocket.on('response', function (d) {
s.write(d.data);
});
});
server.listen(3002, function() { //'listening' listener
console.log('server bound');
});
console.log('Web server running at http://127.0.0.1:3002/');
If the "connections" to Server X would all be TCP-based, you could have an SSH server running on both ends. Server X would then connect to Server Y to only forward some port on Server Y that would point to the SSH server running on Server X. Then you could use a node module like ssh2 to connect to any port on Server X.
Another option for dynamic forwarding would be to set up a socks proxy as described in this answer. From there you could use a socks client module from npm, such as socks5-client.
If instead you have a fixed set of ports that you want have available, you could simplify the above solutions by just having an SSH server on Server Y and Server X connects and creates a port forward for each port you want to have available.
Here is an example of another option: connecting to Server X from Server Y via SSH and opening up connections on Server X using the SSH connection (via ssh2).

node.js listen for UDP and forward to connected http web clients

I'm new to node.js, so forgive the ignorance if this is simple.
What I want to do is setup a simple node.js http server to which a web-client connects. I also want the node.js server to act as a UDP listener on a separate port, on which it will receive JSON payloads from some other application. I want the node.js server to then forward these JSON payloads immediately to one or more of the connected web-clients.
I got this far from some initial googling around:
Create a simple node.js http server that responds with a static html page:
//Initialize the HTTP server on port 8080, serve the index.html page
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'});
res.end(fs.readFileSync(__dirname + '/index.html'));
}).listen(8080, function() {
console.log('Listening at: 127.0.0.1 8080');
}
);
Initialize a UDP server on a separate port:
//Initialize a UDP server to listen for json payloads on port 3333
var srv = dgram.createSocket("udp4");
srv.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
io.sockets.broadcast.emit('message', 'test');
//stream.write(msg);
//socket.broadcast.emit('message',msg);
});
srv.on("listening", function () {
var address = srv.address();
console.log("server listening " + address.address + ":" + address.port);
});
srv.bind(5555);
Use socket.io to establish a live connection between web-client and server:
//this listens for socket messages from the client and broadcasts to all other clients
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
socket.on('message', function (msg) {
console.log('Message Received: ', msg.data.skeletons[0] ? msg.data.skeletons[0].skeleton_id : '');
socket.broadcast.emit('message', msg);
}
);
});
I guess my problem is I don't know how to bridge 2 and 3, to get the received UDP packets broadcasted to the connected socket.io clients. Or perhaps there's a simpler, more elegant way of doing this? I found the documentation for socket.io to be lacking...
EDIT: thanks to the person that fixed the code formatting
I made a running example for you to get going with: http://runnable.com/UXsar5hEezgaAACJ
For now it's just a loopback client -> socket.io -> udp client -> udp server -> socket.io - > client.
here's the core of it:
var http = require('http');
var fs = require('fs');
var html = fs.readFileSync(__dirname + '/index.html');
//Initialize the HTTP server on port 8080, serve the index.html page
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end(html);
}).listen( process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP, function() {
console.log('Listening');
});
var io = require('socket.io').listen(server);
io.set('log level', 0);
io.sockets.on('connection', function (socket) {
socket.emit('message', 'connected');
socket.on('message', function (data) {
console.log(data);
var address = srv.address();
var client = dgram.createSocket("udp4");
var message = new Buffer(data);
client.send(message, 0, message.length, address.port, address.address, function(err, bytes) {
client.close();
});
});
});
var dgram = require('dgram');
//Initialize a UDP server to listen for json payloads on port 3333
var srv = dgram.createSocket("udp4");
srv.on("message", function (msg, rinfo) {
console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
io.sockets.emit('message', 'udp');
});
srv.on("listening", function () {
var address = srv.address();
console.log("server listening " + address.address + ":" + address.port);
});
srv.on('error', function (err) {
console.error(err);
process.exit(0);
});
srv.bind();

Create WebSockets between a TCP server and HTTP server in node.js

I have created a TCP server using Node.js which listens to clients connections.
I need to transmit data from TCP server to HTTP server again in Node.js possibly through a Websocket (socket.io).
However, I do not know how to create such connection such that TCP server is able to push data to HTTP server through Websocket.
Many Thanks.
I was trying lot of things to get this work. Most of the time I was relying on socket.io to get this working, but it was just not working with TCP.
However, net.Socket suffices the purpose.
Here is the working example of it.
TCP Server
var net = require('net');
var HOST = 'localhost';
var PORT = 4040;
var server = net.createServer();
server.listen(PORT, HOST);
server.on('connection', function(sock) {
console.log('CONNECTED: ' + sock.remoteAddress +':'+ sock.remotePort);
sock.write("TCP sending message : 1");
console.log('Server listening on ' + server.address().address +':'+
server.address().port);
}).listen(PORT, HOST);
HTTP Server
var http = require('http').createServer(httpHandler),
fs = require("fs"),
wsock = require('socket.io').listen(http),
tcpsock = require('net');
var http_port = 8888;
var tcp_HOST = 'localhost';
var tcp_PORT = 4040;
/**
* http server
*/
function httpHandler (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);
});
}
http.listen(http_port);
console.info("HTTP server listening on " + http_port);
wsock.sockets.on('connection', function (socket) {
var tcpClient = new tcpsock.Socket();
tcpClient.setEncoding("ascii");
tcpClient.setKeepAlive(true);
tcpClient.connect(tcp_PORT, tcp_HOST, function() {
console.info('CONNECTED TO : ' + tcp_HOST + ':' + tcp_PORT);
tcpClient.on('data', function(data) {
console.log('DATA: ' + data);
socket.emit("httpServer", data);
});
tcpClient.on('end', function(data) {
console.log('END DATA : ' + data);
});
});
socket.on('tcp-manager', function(message) {
console.log('"tcp" : ' + message);
return;
});
socket.emit("httpServer", "Initial Data");
});
Browser Client
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('httpServer', function (data) {
console.log(data);
document.write(data + "\r\n");
socket.emit('tcp', "For TCP");
});
</script>
This way, there is a socket opened between HTTP server and TCP server in Node.js.
If you need to communicate server-server than websockets is probably not a best choice. Try one of RPC libraries, or just use HTTP or your own protocol.
You can use either socket.io or ws (only WebSocket) on Node.js as client (not only in browser)
var io = require('socket.io-client');
var socket = io.connect('http://IP address of Websocket server');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});

Pass data from a Node.js server to a socket.io app

I have this very simple app:
// Require HTTP module (to start server) and Socket.IO
var http = require('http'),
io = require('socket.io'),
url = require('url');
var server = http.createServer(function(req, res){
req.on('data', function(data){
console.log('Received Data');
})
});
server.listen(3000);
// Create a Socket.IO instance, passing it our server
var socket = io.listen(server);
// Add a connect listener
socket.on('connection', function(client){
server.on('data',function(event){
client.send(url.search);
console.log('Received Data from socket app');
});
client.on('disconnect',function(){
console.log('Server has disconnected');
});
});
I need to curl the node server to pass it some post data, then i would like this data to be handed to the socket.io app so that it can feed back to the currently connected clients.
Is there anyway to accomplish that ?
Many thanks,
The socket that you get from
var socket = io.listen(server);
you can always call emit on this to send a message to all connected clients. So in your http server, you can emit the posted data:
var server = http.createServer(function(req, res){
var body = '';
req.on('data', function(data){
console.log('Received Data');
body += data;
});
req.on('end', function() {
// Emit the data to all clients
socket.emit('foo message', body);
});
});

cannot display my variable on browser

I am working on a socket.io + Node.js project.
When I print an variable using console.log, I get my variable on console.
But when I sent this variable to a client, it seems as [object Object] form on browser.
How can I see my variable on browser?
Thanks
Try console.log(JSON.stringify(myVariable)); and then look at it in your browser and you'll gain more insight as to what's happening exactly.
You may be using the 0.6 serverside syntax of:
socket.send({foo: 'bar'})
Try using the following updated syntax:
socket.json.send({foo: 'bar'})
You can find more information here:
https://github.com/LearnBoost/Socket.IO/wiki/Migrating-0.6-to-0.7
thanks, console.log(JSON.stringify(myVariable)); worked for my case. Variable has shown as
{ coloumn_that_result_lays: "result"}. Of course we can overcome it with javascript-substring but is there a function which gives "result" directly.
// Require HTTP module (to start server) and Socket.IO
var io = require('socket.io'),
http = require('http');
io = require('socket.io');
// Start the server at port 8080
var server = http.createServer(function(req, res){
// Send HTML headers and message
res.writeHead(200,{ 'Content-Type': 'text/html' });
res.end('<h1>Hello Socket Lover!</h1>');
});
server.listen(8080);
// Create a Socket.IO instance, passing it our server
var socket = io.listen(server);
// Add a connect listener
socket.on('connection', function (client){
//mysql
var mysql = require('db-mysql');
new mysql.Database({
hostname: 'localhost',
user: 'root',
password: '123123',
database: 'node'
}).connect(function(error) {
if (error) {
return console.log('CONNECTION error: ' + error);
}
this.query('SELECT data FROM exam where id=2 ').
execute(function(error,result) {
if (error) {
console.log('ERROR: ' + error);
return;
}
client.json.send(JSON.stringify(result));
});
});
// Create periodical which ends a message to the client every 5 seconds
var interval = setInterval(function() {
client.send('This is a message from the server! ' );
},1000);
// Success! Now listen to messages to be received
client.on('message',function(event){
console.log('Received message from client!',event);
});
client.on('disconnect',function(){
clearInterval(interval);
console.log('Server has disconnected');
});
});

Resources