3

Goal

I am trying to send data over UDP from a Java server to a Python client on the same machine.

Environment

  • Device/OS: Jetson nano with Ubuntu 18.04.3 LTS (Bionic Beaver)
  • JavaC version: javac 11.0.4
  • Java version:
    • openjdk version "11.0.4" 2019-07-16
    • OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
    • OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode)

Problem

I can send data from a Python test server, see code below, to the Python test client just fine. However, If I try to send data from the Java test server to the Python test client, nothing seems to arrive. The Java server doesn't throw an exception.

Test client in Python (working)

import socket

UDP_IP = "localhost"
UDP_PORT = 9999

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

print("listening...")

while True:
    data, addr = sock.recvfrom(1024)
    print("received message from: ", addr)
    print("payload: ", data)

Test server in Python (working)

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto("Hello World", ("localhost", 9999))

Test server in Java (not working or doesn't reach the python client)

import java.io.*;
import java.net.*;

public class TestSender {
    public static void main(String[] args) {
        try {
            byte[]         data    = "Hello world".getBytes();
            int            port    = 9999;
            InetAddress    address = InetAddress.getLocalHost();
            DatagramPacket packet  = new DatagramPacket(data, data.length, address, port);
            DatagramSocket socket  = new DatagramSocket();

            socket.send(packet);
            System.out.println("Data sent");

            socket.close();

        } catch (Exception e) {
            System.out.println("Something went wrong");
        }
    }
}
kshetline
  • 12,547
  • 4
  • 37
  • 73
KasparJohannes
  • 520
  • 2
  • 7
  • 26
  • 3
    You may try to change `InetAddress.getLocalHost()` to `InetAddress.getByName("localhost")`. Probably, *getLocalHost* is returning your network device address, not the loopback address (127.0.0.1). – Gomiero Nov 23 '19 at 00:35
  • 2
    Seconding the above, the address returned may depend on your system, you can print it out to check it . See this for more information : https://stackoverflow.com/questions/2381316/java-inetaddress-getlocalhost-returns-127-0-0-1-how-to-get-real-ip – Tony Farias Nov 23 '19 at 03:33
  • 2
    Don't bind to localhost. Bind to 0.0.0.0. – user207421 Nov 23 '19 at 06:24

1 Answers1

1

Issue

InetAddress address = InetAddress.getLocalHost();

returns the address of one of the interfaces of the machine.

Solution

As @Gomiero suggested, using either

InetAddress address = InetAddress.getByName("127.0.0.1");
// or
InetAddress address = InetAddress.getByName("localhost");

solves the problem because in this case the client bound to 127.0.0.1 and does not accept packets from any other IP address.

Note

As @user207421 suggested in most cases the proper solution to the problem would be to bind the client to 0.0.0.0 like this:

UDP_IP = "0.0.0.0"
UDP_PORT = 9999
sock.bind((UDP_IP, UDP_PORT))

Binding the client to 0.0.0.0 resolves the issue with using InetAddress.getLocalHost() on the server-side because it makes the client accept data to any of its IP addresses.

However, I finally decided to bind the client to 127.0.0.1 now with the proper understanding of what that does, because I only want data from the local machine.

KasparJohannes
  • 520
  • 2
  • 7
  • 26
  • 1
    I didn't suggest any such thing, and this isn't necessary if you bind to 0.0.0.0, which is what I did suggest, and which is normal practice. – user207421 Nov 23 '19 at 20:33
  • @user207421 You are right, sorry, that was not your suggestion I am changing that. However, `address = InetAddress.getByName("0.0.0.0");` does not seem to work. It results in `java.net.BindException: Cannot assign requested address: Datagram send failed`. – KasparJohannes Nov 23 '19 at 20:47
  • 1
    I didn't say that either. I said to *bind* to 0.0.0.0 instead of localhost. The only bind to localhost here is in the Python code. All this other Java stuff is quite misguided. You should be able to send to a host via any of its reachable IP addresses if you don't prevent it via the bind as you are doing. – user207421 Nov 23 '19 at 21:08
  • @user207421 Thanks, now I understand, I originally did not realise that I should change something on the client-side. That is exactly the answer I was looking for because I was really confused that the original example with `InetAddress.getLocalHost();` did not work. However, binding the client to `127.0.0.1` is exactly what I need since I don't want data from another machine in the network in this case. I just didn't think about the exact mechanics well enough... – KasparJohannes Nov 23 '19 at 21:19