Skip to content

Lost UDP datagrams when sending in socket.send callback #25646

Description

@AE9RB

Linux 4.4.0-17763-Microsoft #253-Microsoft x86_64 GNU/Linux
node versions tried: v8.15.0 v10.15.0 v11.7.0

Use this server or any tool you can listen to UDP with:

require('dgram')
.createSocket('udp4')
.on('message', (msg, rinfo) => {
    msg = `${msg}`.split(' ')[0];
    console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
})
.bind(41234);

Run this to demonstrate the problem:

const dgram = require('dgram');

const WOULD_YOU_LIKE_ME_TO_DROP_BUFFERS = true; // TOGGLE THIS

const PORT = 41234;
const GRAMS = 1000;
const FILL = '##################################################'

function sendgrams() {
    let pos = 0;
    const socket = dgram.createSocket('udp4');
    function funkytown() {
        if (pos >= GRAMS) {
            socket.close((e) => {
                if (e) {
                    console.log(e);
                }
                console.log('Closed.');
            });
            return;
        }
        socket.send(`${pos++} ${FILL}${FILL}${FILL}${FILL}${FILL}${FILL}${FILL}`, PORT, (e) => {
            if (e) {
                console.log(e);
            }
            if (WOULD_YOU_LIKE_ME_TO_DROP_BUFFERS) {
                funkytown();
            } else {
                setTimeout(funkytown, 0);
            }
        });
    }
    funkytown();
}

sendgrams();

If I call socket.send from within its own callback, some UDP datagrams never show up at the destination. The workaround is to let the callback exit first. Here we see server output showing missing datagrams where we expect the log to finish up with "997, 998, 999".

server got: 958 from 127.0.0.1:61866
server got: 988 from 127.0.0.1:61866
server got: 992 from 127.0.0.1:61866

Activity

  1. bnoordhuis commented on Jan 23, 2019

    @bnoordhuis
    Member

    That's not unexpected and not a Node.js issue. UDP is lossy, unreliable. If you transmit faster than the operating system can send out the datagrams, or faster than the intermediate hops can retransmit them, some of them will end up being dropped.

    If you have reason to believe it is a Node.js issue let me know but until then I'm closing this out.

  2. added
    invalidIssues and PRs that are invalid.
    dgramIssues and PRs related to UDP and the dgram module.
    on Jan 23, 2019
  3. AE9RB commented on Jan 23, 2019

    @AE9RB
    Author

    This is a node bug.

  4. AE9RB commented on Aug 22, 2019

    @AE9RB
    Author

    This is still broken in node 12. I know UDP is lossy. That's not the problem. If this is the intended behavior then it needs to be documented because dropping back to the event queue in this situation isn't obvious.

  5. bnoordhuis commented on Aug 22, 2019

    @bnoordhuis
    Member

    You're failing to make a case for why this should be a Node.js issue.

  6. jasnell commented on Aug 22, 2019

    @jasnell
    Member

    Let's try a slightly different way: as @bnoordhuis points out, the current dgram/udp stack in Node.js makes no guarantees that datagram sending is reliable. The code is working as intended. Making udp more reliable is possible, and if it's something that's important to you, a PR will always be considered. In the meantime, we are busy working to implement QUIC support that does add a layer of reliability on top of UDP. In the future, that may be worth exploring.

  7. jacobbogers commented on Jul 25, 2021

    @jacobbogers

    This is a node bug.

    yeah, its a bug, we use setTimeout aswell to solve it,

  8. jacobbogers commented on Jul 25, 2021

    @jacobbogers

    This is still broken in node 12. I know UDP is lossy. That's not the problem. If this is the intended behavior then it needs to be documented because dropping back to the event queue in this situation isn't obvious.

    I tested your code on node 16, it is not an issue anymore, I think somewhere along they way it was solved (not tested on 13,14,15 versions)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dgramIssues and PRs related to UDP and the dgram module.invalidIssues and PRs that are invalid.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions