Node.js flush socket after write

2020-04-17 06:16发布

问题:

I'm implementing a tcp protocol in Node.

Full source:
https://github.com/roelandmoors/ads.js/blob/master/ads.js

specs:
http://infosys.beckhoff.com/content/1033/tcadsamsspec/html/tcadsamsspec_amstcppackage.htm?id=17754

The problem is that I use this to send a package:

this.tcpClient.write(buf);

If I send multiple commands, then multiple commands are combined into a single tcp packet.
This doesn't work.

There are more questions about this on SO, but they recommend using a delimeter.
But since I can't change the protocol this isn't an option.

Isn't there a simple solution to flush the socket?

socket.setNoDelay() doesn't help.

Edit: I also tried to use the drain event to send the next write, but the event is never called?

Update:

This seems to solve the problem, but is very uggly and I don't now if it always works.
Instead of writing it directly I write to a buffer:

this.writeFILO.push(buf);

Every cycle(?) I'm writing a package to the socket stream:

var sendCycle = function(ads) {
    if (ads.writeFILO.length > 0) {
        ads.tcpClient.write(ads.writeFILO.shift());
    }
    setTimeout(function() {
        sendCycle(ads);
    }, 0);
}

回答1:

I refer to the socket.write(data, [encoding], [callback]) API:

The optional callback parameter will be executed when the data is finally written out - this may not be immediately.

So, set up a queue (array is fine) which holds messages to be sent.
When the above callback is being called, check the queue and send if needed..

This however does not guarantee what you're looking for, you'll have to test. Unfortunately the docs don't explicitly state when there's an acknowledgement from the remote end point that it actually received that message...

In the end, as you concluded, TCP is a stream.

An interesting idea which just came up to me now, however, if you're FORCED TO use an existing protocol, then open two TCP connections.
When one connection acknowledges (whatever the higher-level protocol is) receiving that message, send the next through the other one... and so forth..

Anyway, nice challenge :)



回答2:

I know that this is an old question, and I'm not 100% sure I understand what you are looking for, but there is a way to flush a socket in node. First you need to implement a Transform class.

See here for example: https://nodejs.org/api/stream.html#stream_implementing_a_transform_stream.

Then you can take your stream and pipe it through your transform before piping it into your socket.

I do not own this node module but I have seen an example of this here: https://github.com/yongtang/clamav.js/blob/master/index.js#L8



回答3:

I was wrong. TCP is a stream and the protocol works like a stream, but I didn't handle it like a stream.

PS: sending seperate messages seemed to work with setImmediate()