Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Is there a way for one TCP packet one 'data' event? #node 0.10.35 #15443

Closed
dayuoba opened this issue Apr 14, 2015 · 14 comments
Closed

Is there a way for one TCP packet one 'data' event? #node 0.10.35 #15443

dayuoba opened this issue Apr 14, 2015 · 14 comments

Comments

@dayuoba
Copy link

dayuoba commented Apr 14, 2015

As API doc mentioned.socket.nodelay defaults to true,but even i call socket.setNoDelay(true),it didn't work well..
reproduce code:
server.js

var net = require('net');
var fs = require('fs');
var domainSock = '/tmp/domainSock';

var server = net.Server(function handle(socket) {
    socket.setNoDelay(true);
    socket.on('data', function(data) {
        console.log('*');
        console.log(data.toString());
        console.log('*');
    });
});

server.listen(domainSock);

server.on('error', function(e) {
    if (e.code == 'EADDRINUSE') {
        console.log('Address in use, retrying after 1minute..');
        setTimeout(function() {
            try {
                fs.unlinkSync(domainSock);
                //server.close();
            } catch (e) {
                console.log(e);
            }
            server.listen(domainSock);
        }, 1000);
    }
});

client.js

var net = require('net');

var socket = net.connect('/tmp/domainSock');
socket.setNoDelay(true);
socket.on('connect', function listener() {
    console.log('connect');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
    socket.write('data');
});

every time testing.the output is different.i don't know why.did i miss something?

output:

//first time
*
datadatadata
*
*
datadatadatadatadatadatadata
*
//second time
*
datadatadatadatadatadatadata
*
*
datadatadata
*

//third time
*
data
*
*
datadatadatadatadatadatadatadatadata
*

EDIT:I must say, i want one TCP packet one 'data' event was called.

@dayuoba
Copy link
Author

dayuoba commented Apr 15, 2015

No one meets this problem?
i'd changed the string written above 'data' to 'how about making the message verylonggggggggggggggggggggggggg'.
i got the regular output :

*
how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg
*
*
how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg
*

only first time call wirte(),it will send data immediately.

@silverwind
Copy link

There's two reasons why you're seeing this:

  • You need to run .setNoDelay() after the socket has connected for it to work.
  • The TCP stack might coalesce packets. If you inspect the traffic in Wireshark, you should see single 'data' packets.

Check out nodejs/node#906 (comment) and following comments for some more discussion on the causes.

@dayuoba
Copy link
Author

dayuoba commented Apr 18, 2015

thanks for your response @silvewind
tried as you said

var net = require('net');

var socket = net.connect('/tmp/domainSock');

socket.once('connect', function listener() {
//socket.on
    console.log('connect');
    socket.setNoDelay(true);
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
    socket.write('how about making the message verylonggggggggggggggggggggggggghow about making the message verylonggggggggggggggggggggggggg');
});

it still doesn't work...
i'm not sure if there are some differences between TCP and UnixSocket
pls have a note,i use .listen(path) ,not the same as you mentioned at nodejs/node#906 (comment)

@silverwind
Copy link

I think what you're seeing is coalascing of socket writes. One 'data' event isn't always one packet. If you look at it in wireshark, you should see it sending each call in a single packet.

If this is someting considered an issue or not, I can't answer. You should handle your data in a streaming way.

@dayuoba
Copy link
Author

dayuoba commented Apr 18, 2015

@silverwind thanks,i understand what you said.But what i need is one packet one 'data' event
is there any way of implemention of this?

@silverwind
Copy link

I don't fully understand if this is caused by the kernel or by node. It may or may not be a node bug, will research.

@misterdjules
Copy link

@dayuoba Thank you for reporting this issue! There's already an issue that describes setNoDelay being a no-op if the socket is not connected: #8572.

Would you mind editing the title and description of this issue so that it better represent the remaining unknown issue, which is that for multiple TCP packets seem to result in only one 'data' event, and that there's no way to change that?

@dayuoba dayuoba changed the title socket.setNoDelay(true),did not work on Unix Domain Socket #node 0.10.35 Is there a way for one TCP packet one 'data' event? #node 0.10.35 May 7, 2015
@dayuoba
Copy link
Author

dayuoba commented May 7, 2015

@misterdjules ok, thanks for your response.but it did not resolve my issue,and right now i mush add a 'EOF' like symbol at the end of each message for what i want.

@ravi
Copy link

ravi commented May 7, 2015

TCP is a streaming protocol without message boundaries. There is no "packet" at the transport layer.

@dayuoba
Copy link
Author

dayuoba commented May 7, 2015

@ravi i don't know the protocal details,but as i use setNoDelay(true),what i think is it should send data immediately,so i regard it as a packet and what i want is that the server side should emit the 'data' event immediately.

@ravi
Copy link

ravi commented May 7, 2015

@dayuoba that's a fair expectation: setting setNoDelay(true) should disable Nagle's algorithm at the TCP layer. I write to warn you that flushing TCP buffers in real-time provides no guarantee that they will be sent into and across the network in the same segment sizes you wrote them out in from the application, and more importantly, you can have no guarantee that they will be passed (by the network stack) to the receiver with the same packetization. In other words TCP_NODELAY does not imply message boundaries or guarantee message sizes. It just says to the kernel, don't buffer up bytes waiting for TCP acknowledgements, but send them down the wire (TCP window, etc, permitting) as you receive it. How these fragments get chopped up within the network and reassembled at the receiver is out of the scope of this setting (disclaimer: IP has some near-obsolete flags for fragmentation/reassembly control, but let's ignore those).

If you perform one write operation of 300 bytes every 100 milliseconds, the only way Node, sitting atop TCP, can provide them back to the receiver in 300 byte chunks at a time is by imposing its own message boundaries on these messages, because TCP, by design, will not do that. But that is not Node core's task, to provide a sort of de facto application messaging protocol (each application protocol -- HTTP, SMTP, etc -- uses its own semantics).

I am sure, however, that there are modules (not just methods like HTTP or WebSockets) that will provide you messaging semantics above TCP. I would suggest looking at one of these.

Assuming I have understood your issue correctly :-), I hope that helps!

@silverwind
Copy link

@ravi great description.

I think UDP might be the right tool for this job, if transmission errors can be handled in the application itself.

@misterdjules
Copy link

Thank you @dayuoba, @silverwind and @ravi. Closing the coalescing of TCP packets as not an issue. The setNoDelay call not being effective if the socket is not connected is a duplicate of #8572.

@dayuoba
Copy link
Author

dayuoba commented May 8, 2015

@ravi @silverwind 👍 much thx,learnd a lot
@misterdjules thank you all the same 😄

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants