0

I've made simple socket comm. client by using NodeJS V10.x net module and rarely seen wired symptoms which the NodeJS client was killed without any exception message. The client run on the AWS Lambda and there was no exception log or any failed message. Just it had gone....

The sequence is that

  1. My client connects to my ECS server and sends command data successfully.
  2. The server, if it received any command, it would send ACK to client. Of course it sent ACK successfully.
  3. Sometimes, the client had gone/killed/halted without any exception message or failed log on AWS cloud watch.

I've no idea how to trace/fix it, please help.

Here is my function code which connect/send/recv data to server and also it's being in the try...catch.

sendDirectCmd(directCmd){
    return new Promise((resolve, reject)=>{
        let socket = net.connect(port, hostname);
        socket.setTimeout(10000); // 10 sec
        socket.on('connect', async ()=>{
            try{
                log.info('[sendCmd] connected to ECS');
                await socket.write(directCmd);
                log.info('[sendCmd] Sent Cmd');
            }catch(e){
                e.message += `\n : (requester.sendCmd.socket.on) Failed to send Cmd \n`;
                log.error('Error on connect\n', e);
                reject(e);
                socket.end();
            }
        });

        socket.on('data', (data)=>{
            resolve(data);
            socket.end();
        });

        socket.on('timeout', ()=>{
            reject(new Error(`socket Timeout `));
            socket.end();               
        });

        socket.on('error', (err)=>{
            e.message += `\n : (requester.sendCmd.socket.error)socket Error `;
            reject(err);
            socket.end();                
        });
    });
}
  • Do you realize that `net.connect()` isn't expecting a URL, but you are using a function call `getGatewayUrl()` to get the hostname. Is the function just named wrong or is it really returning a URL? – jfriend00 Feb 09 '20 at 01:27
  • @jfriend00 The getGatewayUrl() function would return properly hostname(IP Address) and there was no problem on the connecting and sending data. The problem was only happened after connecting/sending data. – user12241494 Feb 09 '20 at 07:34

1 Answers1

1

I don't know if this is the main problem or the only problem, but this piece of code has potential problems:

    socket.on('data', (data)=>{
        resolve(data);
        socket.end();
    });

A TCP socket is a stream. Data you send at one end of the socket can arrive at the other end in any size chunk and does not necessarily arrive in the same size chunk that the sender sent. This piece of code seems to assume that as soon as any data arrives, all the data is here and the socket can be closed (potentially skipping other data that is still arriving). Unless you're only sending one byte over the socket, that just isn't correct.

Instead, you need some sort of known data format on your socket so you know when you've received a complete packet or message or transmission and you must accumulate data until a full message/packet arrives and it may come in multiple chunks.

There are lots of different ways to do this. If your data is text, you can mark the end of piece of text with a newline character or a null character or any other character that would not occur in your data and you read data until you see the marker that indicates you have a full message. If your data is not text, you can first send a four byte length that tells you how many bytes of data are coming. There are lots of other possible ways to format your data so you can know when you have a full message/packet.

It's also important to know that this issue may not show up on a fast LAN, but could be vulnerable on slower links that might cause data to get broken up into smaller packets.

Note that the webSocket protocol has a very nice convenient, pre-defined packet format that will do all this work for you. You will need a webSocket client on one end and webSocket server on the other in order to use it.

Also see these:

Proper way to establish boundaries for a tcp connection

Does node js "response.on('data', func(chunk))" guarantee the chunk boundary

NodeJs - TCP/IP Socket send/receive serially?

jfriend00
  • 683,504
  • 96
  • 985
  • 979