GithubHelp home page GithubHelp logo

Comments (10)

andrewdavidmackenzie avatar andrewdavidmackenzie commented on September 4, 2024

ZeroMQ book says that using the 255.255.255.255 broadcast will not send it on all interfaces, if you have more than one.

from simpdiscover.

dave-tucker avatar dave-tucker commented on September 4, 2024

👋 192.168.2.255 would work, but it's technically a directed broadcast.
if you're attached to 192.168.2.0/24 it will get converted a L2 broadcast, otherwise it will be sent to the your default router... if your router is attached to the network, it will send it as a L2 broadcast, otherwise it will get routed to a router that is connect to that network and then eventually end up as a broadcast.

in theory at least...

because in practice it was directed broadcast is usually disabled on routers

255.255.255.255 will broadcast to the local network only. if you have multiple interfaces though I'm not sure which one would get picked, but my understanding is that it will indeed pick only one.

Update:

When sending, a socket bound with INADDR_ANY binds to the default IP address, which is that of the lowest-numbered interface.

So as you bind to 0.0.0.0:0 then the lowest numbered interface would be picked to send the broadcast.

from simpdiscover.

andrewdavidmackenzie avatar andrewdavidmackenzie commented on September 4, 2024

When I tried the alternate broadcast address, nothing worked, even within subnet....I can retry though.

from simpdiscover.

dac1976 avatar dac1976 commented on September 4, 2024

I'm currently porting some C++ code to Rust and while porting our network code I ran into the issue you describe here. I can broadcast with Rust sockets using 255.2555.255.255 but not with other valid broadcast addresses. This works fine in C++ using native Windows and Linux sockets, as well as Boost ASIO sockets but for the life of me haven't managed to get this working in Rust.

So far I've tried tokio UdpSocket the std UdpSocket and event manipulating socket options with socket2 crate.

I feel like I'm clearly missing something. I have multicast working and unicast just not broadcast.

Did you ever find a solution to this issue?

from simpdiscover.

andrewdavidmackenzie avatar andrewdavidmackenzie commented on September 4, 2024

Looking back at my code I see I added this comment that explains all I have found out to date

/// A broadcast address is always relative to a given network. When you have a network, you can
/// compute its broadcast address by replacing all the host bits with 1s; simply put, the broadcast
/// address is the highest numbered address you can have on the network, while the network address
/// is the lowest one (with all host bits set to 0s); this is why you can't use either of them
/// as actual host addresses: they are reserved for this use.
///
/// If your network is `192.168.1.0/24`, then your network address will be `192.168.1.0`
/// and your broadcast address will be `192.168.1.255`
///
/// If your network is `192.168.0.0/16`, then your network address will be `192.168.0.0`
/// and your broadcast address will be `192.168.255.255`
///
/// `255.255.255.255` is a special broadcast address, which means "this network".
/// It lets you send a broadcast packet to the network you're connected to, without actually
/// caring about its address.
///
/// See [wikipedia article](https://en.wikipedia.org/wiki/Broadcast_address) for more info
const BROADCAST_ADDRESS : &str = "255.255.255.255";
```

I copied that from some other post I found.

I have not found a way to get broadcasts to work from an address other than that, and I have it hardcoded in this lib.
:-( 

from simpdiscover.

dac1976 avatar dac1976 commented on September 4, 2024

Hmmm, ok weird. A socket should allow sending to a valid broadcast address so long as it's configured correctly.

Frustratiung as this "Just works" in C++ by various means.

I suppose either something is inherently being disallowed in Rust's socket implementation and/or there is some option that needs to be enabled for it to fully work. Although I think I have all the required options set, Basically I have duplicated the socket options we set in our C++ code using the equivalent functions and settings within Rust's sockets.

I guess I'll keep digging.

Thanks for the reply.

from simpdiscover.

andrewdavidmackenzie avatar andrewdavidmackenzie commented on September 4, 2024

Maybe try an issue to the rust source repo responsible for the networking calls, with a reproduction (rust playground) and sample C++ calls that work?

from simpdiscover.

dac1976 avatar dac1976 commented on September 4, 2024

Solved the problem. It's the bind("0.0.0.0:0").

For the sending socket to broadcast (to all legal broadcasts addresses you could define) you need to create a socket without binding it then setup up the required options. You cannot do this with the std::net:UdpSocket or tokio::net::UdpSocket.

However, you can do this if you use the crate socket2. You can then setup your socket from scratch using socket2, then convert to std::net::UdpSocket, then to something like tokio::net::UdpSocket.

For example:

            let actual_socket_buf_size: usize = 8388608;

            let socket2 = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::UDP))
                .into_diagnostic()
                .wrap_err("Failed to create new socket2::Socket with Domain::IPV4, Type::DGRAM, Protocol::UDP.")?;
            socket2
                .set_send_buffer_size(actual_socket_buf_size)
                .into_diagnostic()
                .wrap_err("Failed to set SO_SNDBUF.")?;
            socket2
                .set_nonblocking(true)
                .into_diagnostic()
                .wrap_err("Failed to set nonblocking mode.")?;
            socket2
                .set_broadcast(true)
                .into_diagnostic()
                .wrap_err("Failed to set SO_BROADCAST.")?;
            let std_socket: std::net::UdpSocket = socket2.into();
            self.socket= tokio::net::UdpSocket::from_std(std_socket)
                .into_diagnostic()
                .wrap_err("Failed to convert to tokio::net::UdpSocket.")?;

Then I can send using:

            let bytes_sent = self.socket
                .send_to(buffer, self.target)
                .await
                .into_diagnostic()
                .wrap_err("Failed to send message via UDP socket.")?;

Setting up a receiving socket is as before and should obviously still be bound correctly.

Using this I can send to 160.51.255.255 and I receive the messages.

Hope ths is of use to you, thought I'd let you know how to solve it.

Edit: Reason I discovered this was reviewing my C++ code both our very old native socket code using WInsock plus our modern C++17 code using boost ASIO sockets, where I realised I never bind the UDP socket for sending only receiving.

from simpdiscover.

andrewdavidmackenzie avatar andrewdavidmackenzie commented on September 4, 2024

Nice work, well done!
Maybe document that (for rust) somewhere that other searchers will find!
Closing issue, if that is OK?

from simpdiscover.

dac1976 avatar dac1976 commented on September 4, 2024

Go for it. Yes will try and put this on Rust forums somewhere when I get a spare moment.

from simpdiscover.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.