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?

10,391

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:

  1. 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.

  2. 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 the while(close_connection_flag == false) loop!

  3. 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 the tcp_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);
    }
  });
});
Share:
10,391

Related videos on Youtube

0x01Brain
Author by

0x01Brain

Updated on September 15, 2022

Comments

  • 0x01Brain
    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
    0x01Brain over 8 years
    Thanks, that might be it.
  • 0x01Brain
    0x01Brain over 8 years
    Sir, 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 that flag_raised_by_server is not initialized inside the switch case block, why?
  • helmbert
    helmbert over 8 years
    In 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 when flag_raised_by_server is actually set. Maybe that helps, too.
  • 0x01Brain
    0x01Brain over 8 years
    Yes you're right, i got the tcp relpy as: <Buffer 74 65 73 74 0a>
  • helmbert
    helmbert over 8 years
    Ah yes, that's a raw byte buffer. You should be able to convert it to a regular string using data.toString().