How can i wait for data until it get received in Node.js from a TCP server while GET request is sent by the user?
Solution 1
If I understood the question correctly, you want to send the HTTP response as soon as you've received a response from your downstream socket server.
First of all, the most important thing to consider: Socket connections -- like almost everything -- in Node.JS are asynchronous.
This has some very important consequences:
-
The call to
tcp_client.on('data', ...)
will not block your program execution until you've received some data. It will simply register a callback function that will (may) be called at some later point in time and then continue your program.This means that if you register a callback in your TCP client and then send the HTTP reponse, the HTTP response will be sent first, and your callback will be called at some later point in time.
-
There is no need to use a while loop for polling on your socket; simply use the
tcp_client.on('data', ...)
method once to register a callback function that is called as soon data is read from the socket.As
tcp_client.on(...)
is asynchronous, it will return immediately; if you do so in a loop, you'll basically spin endlessly and constantly register new event listeners. So, lose thewhile(close_connection_flag == false)
loop! -
If you want to wait with your HTTP response until you've received data on your TCP socket, simply put your
res.end(...)
call inside thetcp_client
callback.
All in all, I'd suggest something like this:
app.get('/', function(req, res) {
tcp_client.on('connect', function(){
console.log('[+] Connected.');
tcp_client.write('HelloServerSideFrom:Client-Server');
});
tcp_client.on('data', function(data) {
var flag_raised_by_server;
switch(data){
case 'HelloClientServerFrom:Server':
close_connection_flag = true;
break;
case 'data-success':
close_connection_flag = true;
flag_raised_by_server = 'ds';
break;
case 'data-failure':
close_connection_flag = true;
flag_raised_by_server = 'df';
break
default:
// do nothing.
break;
}
if (flag_raised_by_server) {
res.end('flag raised by server is: ' + flag_raised_by_server);
tcp_client.destroy();
}
});
});
Solution 2
Instead of setting close_connection_flag
to true, just close the connection right there and return to the user. What you're doing here is creating a memory leak with an infinite amount of listeners on the tcp_client
.
app.get('/', function(req, res) {
tcp_client.on('connect', function(){
console.log('[+] Connected.');
tcp_client.write('HelloServerSideFrom:Client-Server');
});
tcp_client.on('data', function(data) {
switch(data){
case 'HelloClientServerFrom:Server':
close_connection_flag = true;
break;
case 'data-success':
close_connection_flag = true;
flag_raised_by_server = 'ds';
break;
case 'data-failure':
close_connection_flag = true;
flag_raised_by_server = 'df';
break
default:
// do nothing.
break;
}
if (close_connection_flag) {
tcp_client.destroy();
res.end('flag raised by server is: ' + flag_raised_by_server);
}
});
});
Related videos on Youtube
0x01Brain
Updated on September 15, 2022Comments
-
0x01Brain over 1 year
I want to send a hello message to a C++ based server that is listening over port "9090" once the message is sent, the server will do some job or task that will take some time, so i don't want to leave the app.get(); function block, how can i do that until getting a data from server then send back to the user as a response?
Basically what i want is to not reply the user, stay inside the loop while(close_connection_flag == false) until it set to true to leave the loop (until i get a tcp-reply data) then leave the loop and reply the user.
The code i have:
var net = require('net'); var tcp_client = new net.Socket(); var express = require('express'); var app = express(); var close_connection_flag = false; var flag_raised_by_server = ''; app.get('/', function(req, res) { tcp_client.on('connect', function(){ console.log('[+] Connected.'); tcp_client.write('HelloServerSideFrom:Client-Server'); }); while(close_connection_flag == false) { tcp_client.on('data', function(data) { switch(data){ case 'HelloClientServerFrom:Server': close_connection_flag = true; break; case 'data-success': close_connection_flag = true; flag_raised_by_server = 'ds'; break; case 'data-failure': close_connection_flag = true; flag_raised_by_server = 'df'; break default: // do nothing. break; } }); } res.end('flag raised by server is: ' + flag_raised_by_server); tcp_client.destroy(); });
Note: I'm still newbie in
Node.js
, so if you could please provide some comments or explanation of the example code if you provide a one, thanks. -
0x01Brain over 8 yearsThanks, that might be it.
-
0x01Brain over 8 yearsSir, I have a problem that
flag_raised_by_server
variable is empty, and the response i'm getting is:flag raised by server is:
it look thatflag_raised_by_server
is not initialized inside the switch case block, why? -
helmbert over 8 yearsIn that case you might want to inspect what the TCP server actually responds with; try starting with a
console.log(data)
in your callback to see if the server actually sends the expected response. Also, I've adjusted my code example to send the HTTP response only whenflag_raised_by_server
is actually set. Maybe that helps, too. -
0x01Brain over 8 yearsYes you're right, i got the tcp relpy as: <Buffer 74 65 73 74 0a>
-
helmbert over 8 yearsAh yes, that's a raw byte buffer. You should be able to convert it to a regular string using
data.toString()
.