如何选择发送 UDP 广播数据包的网络接口

发布于 2025-01-02 07:29:56 字数 474 浏览 1 评论 0原文

如果我发送一个包含“foo”的UDP数据包,如下所示:

socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send('foo', 0, '<broadcast>', 40001)

然后wireshark告诉我数据包已正确发送,但不幸的是它的源地址是192.168.0.3。由于我的服务器正在侦听 localhost:40001,这意味着它没有收到数据包。我不想让服务器侦听 0.0.0.0,因为它不应该接收在另一个网络中发送的类似 UDP 请求。我可以让服务器在 192.168.0.0/24 网络内侦听,但稍后它将从另一个网络侦听,该网络既不是 localhost 也不是 192.168.0.0/24,因此这并不能解决问题。

有没有办法选择客户端套接字发送数据包的源地址(以及通过哪个接口)?

If I send a UDP packet containing 'foo' like this:

socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send('foo', 0, '<broadcast>', 40001)

then wireshark tells me the packet gets sent correctly, but unfortunately its source address is 192.168.0.3. As my server is listening on localhost:40001, that means it doesn't receive the packet. I don't want to let the server listen on 0.0.0.0, as it shouldn't receive similar UDP requests that are sent within another network. I can make the server listen within the 192.168.0.0/24 network, but later on it will be listening from another network, that is neither localhost nor 192.168.0.0/24, so that doesn't solve the problem.

Is there a way to choose the source address from which (and the interface via which) the client socket will send its packet?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沫离伤花 2025-01-09 07:29:56

我猜你正在尝试将其发送到环回设备,所以它应该类似于(从未使用 ruby​​ 尝试过此操作):

dev="lo"
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BINDTODEVICE, dev+'\0'))

你可能还必须启用多播循环:

socket.setsockopt(Socket::SOL_SOCKET, Socket::IP_MULTICAST_LOOP, [1].pack('i'))

I guess you're trying to send it out to the loopback device, so it should be something like (never tried this with ruby):

dev="lo"
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BINDTODEVICE, dev+'\0'))

you also might have to enable multicast loop:

socket.setsockopt(Socket::SOL_SOCKET, Socket::IP_MULTICAST_LOOP, [1].pack('i'))
赠我空喜 2025-01-09 07:29:56

您尝试过 bind() 了吗?一般来说,如果您 socket.bind() 到某个地址(例如 127.0.0.1),那么您的数据包应源自该地址。环回和广播可能会被特殊对待,但 bind() 将是我尝试的第一选择。

Have you tried bind() yet? Generally speaking, if you socket.bind() to an address (such as 127.0.0.1) then your packets should originate from that address. The loopback, and broadcasts for that matter, might be treated specially but bind() would be my first choice to try.

小情绪 2025-01-09 07:29:56

答案出现晚了两年,但这可能对未来的 StackOverflow 用户有所帮助。看来您需要使用套接字选项IP_MULTICAST_IF,它采用接口地址的网络有序 DWORD 版本。幸运的是,ipaddr 库有一个用于转换人类可读地址的实用方法:

address = '127.0.0.1'
hton = IPAddr.new(address).hton
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF, hton)

Answer appearing two years too late, but this might help future StackOverflow users. It looks like you need to use socket option IP_MULTICAST_IF, which takes a network ordered DWORD version of your interface address. Fortunately the ipaddr library has a utility method for converting human readable addresses:

address = '127.0.0.1'
hton = IPAddr.new(address).hton
socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_MULTICAST_IF, hton)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文