如何在 Java 中获取 DatagramSocket (UDP) 的本地地址
How to get local address of a DatagramSocket (UDP) in Java
我正在 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)是否可以。
更新一:
绑定一个接口而不是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());
}
}
那个DatagramSocket的本地地址是0.0.0.0:53。您在构造它时指定的那个。它使用哪个接口进行回复由静态 IP 路由表决定。不是通过这个代码。而获取DatagramSocket的本地地址,甚至数据报的目标地址(你可以在C中获取但不是Java),如果它是一个问题,将不会帮助你解决这个问题。
my code does not know which interface the packet is received from.
正确。它不在乎。它正在监听所有 IP 地址。你告诉它这样做。它只关心远程地址,你没有显示但显然是正确的。
try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
我不知道你为什么发了两次。
您遇到的是静态 IP 路由问题。不是编程问题。
我正在 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)是否可以。
更新一:
绑定一个接口而不是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());
}
}
那个DatagramSocket的本地地址是0.0.0.0:53。您在构造它时指定的那个。它使用哪个接口进行回复由静态 IP 路由表决定。不是通过这个代码。而获取DatagramSocket的本地地址,甚至数据报的目标地址(你可以在C中获取但不是Java),如果它是一个问题,将不会帮助你解决这个问题。
my code does not know which interface the packet is received from.
正确。它不在乎。它正在监听所有 IP 地址。你告诉它这样做。它只关心远程地址,你没有显示但显然是正确的。
try (DatagramSocket socket = new DatagramSocket(new InetSocketAddress("0.0.0.0", 53))) {
我不知道你为什么发了两次。
您遇到的是静态 IP 路由问题。不是编程问题。