【问题标题】:How to get local address of a DatagramSocket (UDP) in Java如何在 Java 中获取 DatagramSocket (UDP) 的本地地址
【发布时间】:2015-11-26 10:33:15
【问题描述】:

我正在使用 Java 中的 DatagramSocket (UDP) 实现 DNS 服务器,代码如下所示:

try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
    DatagramPacket request = ... // Init Packet
    socket.receive(request);
    ... // Parse request, Resolve, then Generate reesponse
    socket.send(response);
}

它在我的 PC 和大多数服务器(包括 aws、linode 等)上运行良好,但在具有双以太网适配器的服务器上运行不佳。

此服务器有一个网络配置:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.1.204
netmask 255.255.255.0

auto eth1
iface eth1 inet static
address 192.168.1.207
netmask 255.255.255.0

当我测试这个 DNS 时,我得到:

# nslookup
> server 192.168.1.207
Default server: 192.168.1.207
Address: 192.168.1.207#53
> info.dev.
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; reply from unexpected source: 192.168.1.204#53, expected 192.168.1.207#53
;; connection timed out; no servers could be reached
>

它似乎从 eth1 (192.168.1.207) 收到一个数据包,但发送到 eth0 (192.168.1.204)。而且我的代码不知道数据包是从哪个接口接收的。

try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
    ...
    socket.receive(request); // local socket address not known :-(
    ...
    socket.send(response); // local socket address not known :-(
}

Socket(TCP)可以做到这一点,但我不知道DatagramSocket(UDP)是否可以做到。

更新-1:

绑定一个接口而不是0.0.0.0,效果很好。

更新 2:

Socket (TCP) 可以获取本地地址和远程地址:

try (ServerSocket server = new ServerSocket(23)) {
    try (Socket socket = server.accept()) {
        System.out.println(socket.getLocalSocketAddress());
        System.out.println(socket.getRemoteSocketAddress());
    }
}

【问题讨论】:

  • 0.0.0.0 基本意思是“所有接口”,你不能把socket绑定到一个接口吗?
  • 我不明白这个问题。 DatagramSocket 的本地地址是 0.0.0.0:53。您在构建它时指定的那个。它使用哪个接口进行回复由静态 IP 路由表确定。不是通过这个代码。不是编程问题:题外话。
  • @AndersR.Bystrup,绑定一个(例如 192.168.1.207)就可以了。
  • 接受的 TCP 套接字的本地地址是客户端使用的目标地址。 UDP 没有接受的套接字,所以它没有那个。如果您打印出 ServerSocket 的本地地址,您将得到 0.0.0.0:23,这与您为 DatagramSocket 所做的非常相似,并且出于相同的原因。在 C 级别有一个 API 可以获取 数据报 的目标地址,但它没有在 Java 中实现。

标签: java dns udp


【解决方案1】:

DatagramSocket 的本地地址是 0.0.0.0:53。您在构建它时指定的那个。它使用哪个接口进行回复由静态 IP 路由表确定。不是通过这个代码。并且获取 DatagramSocket 的本地地址,甚至是数据报的目标地址(您可以在 C 中获取,但在 Java 中不能获取),如果这是一个问题,将无法帮助您解决这个问题。

我的代码不知道数据包是从哪个接口接收的。

正确。它不在乎。它正在侦听所有 IP 地址。你告诉它这样做。它只关心远程地址,您没有显示但显然正确。

try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {

我不知道你为什么发了两次。

您遇到的是静态 IP 路由问题。不是编程问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2017-10-27
    • 2010-09-06
    • 1970-01-01
    • 2014-06-26
    • 2012-05-31
    相关资源
    最近更新 更多