Java UDP-Pakete über Android senden

Anub1s

Lieutenant
Registriert
Aug. 2006
Beiträge
716
Hallo zusammen,

ich bin gerade meine erste Android-App am programmieren, nutze dazu Android Studio unter Windows 7. Ich möchte ein UDP-Paket an einen Rechner versenden. Wenn ich meinen Code im Emulator in Android Studio laufen lassen, funktioniert die App auch und tut was sie soll, das UDP-Paket kommt auf dem Zielrechner einwandfrei an. Wenn ich die App allerding statt auf dem Emulator auf meinem realen Smartphone (Nexus 5) starte (was von der grafischen Oberfläche auch einwandfrei funktioniert) kommt kein Paket beim Zielrechner an.
Sämtliche Ergebnisse, die ich über Google finde, beschäftigen sich eigentlich immer nur mit Problemen, dass es auf dem realen Gerät funktioniert und im Emulator nicht, aber zu dem Problem genau umgekehrt wie bei mir nichts :(

Hier mal Auszüge aus meinem Code:

Code:
class SendUdpDataTask extends AsyncTask<Integer, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Integer... params) {
        byte[] bytes = new byte[3];
        int port = 8888;
        InetAddress address = null;
        try {
            address = InetAddress.getByName("192.168.0.199");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        int x = params[0];
        int y = params[1];
        int z = params[2];
        bytes[4*i + 1] = (byte) x;
        bytes[4*i + 2] = (byte) y;
        bytes[4*i + 3] = (byte) z;

        try {
            DatagramSocket socket = new DatagramSocket();
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
            socket.send(packet);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        Button sendButton = (Button) findViewById(R.id.send_button);
        sendButton.setText("done");
    }
}

public void sendData(View view) {
    new SendUdpDataTask().execute(1, 2, 3);
}

In der AndroidManifest.xml habe ich lediglich
Code:
 <uses-permission android:name="android.permission.INTERNET" />
hinzugefügt.

Wenn ich die App im Emulator laufen lasse, kommt genau das UDP-Paket mit den 3 Bytes an, auf dem realen Gerät passiert nichts.
Mein PC (auf dem Android Studio und der Emulator laufen) und der Zielrechner (192.168.0.199) hängen im selben Subnetz (über einen Switch verbunden), mein Smartphone hängt über WLAN an einem AP der ebenfalls an den Switch angeschlossen ist. Über ConnectBot kann ich von meinem Smartphone aus den Zielrechner auch einwandfrei anpingen.


Kann es ein Problem mit dem WLAN sein, dass hierüber die UDP-Pakete (generell) nicht gesendet werden können? Oder fehlen mir noch speziell Berechtigungen, die ich in der Manifest-Datei anfordern muss? Allerdings fände ich das seltsam, da es ja im Emulator funktioniert.


Über Tipps oder Vorschläge, was ich probieren könnte, wäre ich euch sehr dankbar :)


MfG Anub1s
 
Teiby schrieb:
Windows firewall. Port freischalten. Außerdem ist die netzadresse ungewöhnlich. Zusätzlich ist die IP kein hostname
An der Windows-Firewall kann es na nicht liegen, wie oben geschrieben geht es ja um das Senden von Paketen von meinem Smartphone an den Zielrechner (auf dem ebenfalls kein Windows läuft). Im Emulator von Android Studio funktioniert es ja einwandfrei.
Was ist an der Netzadresse (meinst du die 192.168.0.199) ungewöhnlich? Dass ich über getByName auch die IP verwenden kann hatte ich irgendwo gelesen, und im Emulator klappt es damit ja auch ohne Probleme. Wie bekomme ich sonst ein passendes InetAddress-Objekt?

Liron schrieb:
Kannst ja auch mal mit Wireshark die Pakete im Netzwerk verfolgen
Aber wo lasse ich Wireshark dann laufen? Auf meinem Smartphone stelle ich mir das schwierig vor :(, und auf dem PC funktioniert ja alles wie es soll ...
 
Handy ist im WLAN, und die IP-Adresse des Zielrechner ist auch vom Handy aus anpingbar.
 
Anub1s schrieb:
Senden von Paketen von meinem Smartphone an den Zielrechner
Meist sind Firewalls so eingestellt, dass diese nur Verbindungen raus lassen, aber nichts rein lassen wegen Sicherheitslücken. In dem Fall funktioniert das Senden, aber nicht das Empfangen, weil der PC nein sagt.
Es hat im Emulator funktioniert, weil das Paket nicht von außerhalb kommt und damit nicht "gefährlich" ist.

Anub1s schrieb:
Was ist an der Netzadresse (meinst du die 192.168.0.199) ungewöhnlich?
Gehen wir von einem /24 Netz aus, so ist 192.168.0.x das Subnetz Zero, was ungewöhnlich ist (normal gehts bei 192.168.1.x los)

Anub1s schrieb:
Dass ich über getByName auch die IP verwenden kann hatte ich irgendwo gelesen, und im Emulator klappt es damit ja auch ohne Probleme. Wie bekomme ich sonst ein passendes InetAddress-Objekt?
http://download.java.net/jdk7/archive/b123/docs/api/java/net/InetAddress.html#getByAddress(byte[])
Damit z.B. InetAddress.getByName(new byte[] {192, 168, 0, 199});
 
Auf dem Zielrechner (der nicht der Rechner mit der Entwicklungsumgebung ist) läuft keinerlei Firewall oder ähnliches, es wird also in beiden Fällen von einem Client an einen anderen gesendet.
Brauche ich ggf noch weitere Berechtigungen in der Manifest-Datei, um über WLAN meine UDP-Pakete senden zu dürfen?

Logcat sagt mirnoch nichts, werde ich mir aber mal anschaun.
 
Teiby schrieb:
Gehen wir von einem /24 Netz aus, so ist 192.168.0.x das Subnetz Zero, was ungewöhnlich ist (normal gehts bei 192.168.1.x los)
Das musste ich jetzt glatt googlen. Den Begriff hatte ich vorher noch nie gehört und ich weiß jetzt auch warum: Schon RFC1878 vom Dezember 1995 (mittlerweile veraltet) beschreibt diese Praxis als obsolet. Das Subnetz ist gültig und bereitet heutigem Netzwerkequipment keinerlei Probleme. :) Daran liegt das vom TE beschriebene Problem garantiert nicht.

Edit: Zum eigentlichen Problem fällt mir noch ein: Läuft auf dem Smartphone eine Virenscanner- oder Firewall-App? Die könnten das Paket droppen.
 
Zuletzt bearbeitet:
Zu der Sache mit getByName(): Die Dokumentation erlaubt es.

The host name can either be a machine name, such as "java.sun.com", or a textual representation of its IP address. If a literal IP address is supplied, only the validity of the address format is checked.

Wäre ja auch ziemlich dämlich wenn nicht. Überall wo man einen Hostnamen angeben kann kann man auch eine IP angeben. Wenn jetzt jeder Anwendungsentwickler selber Code schreiben müsste um zwischen Hostname und IP zu unterscheiden...

Die Socket API in C geht übrigens noch ein Stück weiter. Wenn man dort einen Port angibt, dann wird dieser als String übergeben. Wenn man dann "80" oder "http" übergibt, kommt in beiden Fällen ein Int mit Wert 80 raus.


asdfman schrieb:
192.168.0.0 ist aber ein /16 Subnet. Wieso gehst du von /24 aus?
Aus deinem Link:
The Internet Assigned Numbers Authority (IANA) has reserved the
following three blocks of the IP address space for private internets:

10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)

We will refer to the first block as "24-bit block", the second as
"20-bit block", and to the third as "16-bit" block. Note that (in
pre-CIDR notation) the first block is nothing but a single class A
network number, while the second block is a set of 16 contiguous
class B network numbers, and third block is a set of 256 contiguous
class C network numbers
.

256 Class C Netzwerke. Ein Class C Netzwerk ist Subnetz /24.
Edit: Das Wort Prefix bezieht sich auf die identischen Bits die den jeweiligen Block bilden.

Edit 2: Das mit dem Subnetz /24 ist halt die Anlehnung an das veraltete Class C.
Aber genauso gut kann man heute den Block in alle möglichen Subnetze ab /16 zerlegen.
 
Zuletzt bearbeitet:
Zurück
Oben