auntyellow auntyellow - 7 months ago 34
Java Question

How to get local address of a DatagramSocket (UDP) in Java

I'm implementing a DNS server with DatagramSocket (UDP) in Java and the code looks like:

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);
}


It works fine on my PC and most servers (including aws, linode, etc), but does not work well on a server with double ethernet adapter.

This server has a network config:

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


When I test this DNS, I get:

# 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
>


It seems to receive a packet from eth1 (192.168.1.207) but send to eth0 (192.168.1.204). And my code does not know which interface the packet is received from.

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) can do this but I do not know whether DatagramSocket (UDP) can do so.

UPDATE-1:

bind one interface instead of 0.0.0.0, it works fine.

UPDATE-2:

Socket (TCP) can get both local and remote address:

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

EJP EJP
Answer

The local address of that DatagramSocket is 0.0.0.0:53. The one you specified when you constructed it. Which interface it uses to reply on is determined by the static IP routing tables. Not by this code. And getting the local address of the DatagramSocket, or even the target address of the datagram (which you can get in C but not Java), wouldn't help you to solve this problem, if it is a problem.

my code does not know which interface the packet is received from.

Correct. It doesn't care. It is listening at all IP addresses. You told it to do that. It only cares about the remote address, which you haven't shown but have clearly got correct.

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

I don't know why you've posted this twice.

What you have here is a static IP routing issue. Not a programming problem.

Comments