Home > Back-end >  Is a udp broadcast expected to loop back?
Is a udp broadcast expected to loop back?

Time:11-21

I have an udp time server coded in c (for linux). Later, I will install it in a sensor array, but for the moment I am testing it locally on my development machine by just listening to 127.0.0.1 in my client. The thing is, when I broadcast to INADDR_BROADCAST, it does not work, while if I explicitly send the datagrams to INADDR_LOOPBACK, then it works like a charm.

Is this behavior expected from UDP? I know that my university is probably shutting all udp ports by default, but I also found a question here on StackOverflow whose answer states that in theory the datagram for my local computer should actually never leave. I also found this answer, but I am not certain if the problem is similar.

My server code is:

int main(int argc, char** argv) {

    uint16_t broadcast_port = 5070;

    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in s;

    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    printf("Starting time broadcast udp server on port %u\n", broadcast_port);

    int broadcastEnable=1;
    int ret=setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable));

    memset(&s, '\0', sizeof(struct sockaddr_in));
    s.sin_family = AF_INET;
    s.sin_port = htons(broadcast_port);
    s.sin_addr.s_addr = htonl(INADDR_BROADCAST);

    signal(SIGINT, interuptHandler);

    uint8_t timesByteArray[sizeof(uint64_t)];

    while (goon) {
    
        int flags = 0;
    
        uint64_t ms = time_ms();
        orderTimeBytes(ms, timesByteArray);
    
        int b_written = sendto(sockfd, timesByteArray, sizeof(uint64_t), flags, (struct sockaddr *) &s, sizeof(s));
    
        if (b_written < 0) {
            perror("Failed to write a datagram");
        }
    
        sleep_ns(500000);
    
    }

    printf("\nClosing time broadcast udp server\n");

    close(sockfd);

    return 0;
}

CodePudding user response:

by just listening to 127.0.0.1 in my client. The thing is, when I broadcast to INADDR_BROADCAST, it does not work, while if I explicitly send the datagrams to INADDR_LOOPBACK, then it works like a charm

TLDR: Your recv socket should bind to INADDR_ANY.

You didn't share your client code, but I believe your recv socket needs to bind to INADDR_ANY (0.0.0.0).

    struct sockaddr_in s = {0}; // zero it all out
    s.sin_family = AF_INET;
    s.sin_port = htons(broadcast_port);
    s.sin_addr.s_addr = htonl(INADDR_ANY); // effectively a no-op since s is already zero'd out.

    bind(sock, (sockaddr*)&s, sizeof(s));

The send/recv relationship between real and loopback adapters will vary between platforms - especially Windows and Linux. But if I had to guess, when you send to 255.255.255.255, the routing table is consulted and resolves that address to the default real adapter and IP address. That stack doesn't necessarily hairpin back to sockets listening explicitly on the loopback adapter.

I recall sending to 127.0.0.1 explicitly does work when the listen socket is listening on INADDR_ANY. So I'm guessing that broadcast traffic will have similar behavior.

  • Related