# UDP Problem



## Big_Daddi (4. Aug 2009)

Hi hi,

ich habe folgendes Problem. Und zwar versuche ich vergebens eine UDP datenübertragung herzustellen. Jedoch hab ich dabei "leichte" Probleme. Ich habe folgenden Quellcode auch schon versucht:

```
import java.net.DatagramPacket;
import java.net.DatagramSocket;

class WriteServer {
  public static void main(String args[]) throws Exception {
    int clientPort = 999;

    int buffer_size = 1024;

    byte buffer[] = new byte[buffer_size];
    DatagramSocket ds = new DatagramSocket(clientPort);
    while (true) {
      DatagramPacket p = new DatagramPacket(buffer, buffer.length);
      ds.receive(p);
      System.out.println(new String(p.getData(), 0, p.getLength()));
    }
  }
}
```

Jedoch wenn ich das Programm laufen lasse, macht er mir eine Endlosschleife und in der Console kommt nur "null" in rot und das die ganze zeit!
Vielleicht ist das nicht der richtige Port??? Ich bin ratlos. Hab schon nen Portscan durchgeführt und da hat er mir gesagt Port 88 und 548 sind offen. Aber mit denen geht es auch nicht!
Kann es auch daran liegen dass es ein MAC ist und kein Windows Rechner?? Sollte aber normalerweise ja nichts ausmachen oder?

Den Sendeteil der funktioniert, da sagt auch meine Firewall dass sie etwas an eine IP-Adresse durchgelassen hat. Jedoch der Empfang will nicht so ganz!

Sorry für die vielen Fragen aber ich noch ein wenig ein Neuling!

Danke schon mal im Voraus!

Gruß


----------



## Geeeee (4. Aug 2009)

soweit ich weiß, kann man doch als User (in *nix-Systemen) Ports > 1000 (oder war es sogar die wunderschöne Zahl 1024) öffnen.


----------



## dayaftereh (4. Aug 2009)

Hey

Also ich habe es auch mal ausgeführt, bei mir bleibt es bei der receive() Methode Stehen, was ja auch richtig ist, weil die so lange blockiert bis daten ankommen. Meine frage ist, du hast hier eine Server geschieben der auf dem Port 999 lauscht, du brauchst natürlich auch einen client der sich zu diesen Port verbindet, wo ist der oder was für eine Service steckt dahinter.

Ich habe mal eine Kleines UDP Server - Client beispiel gemacht:

UDPServer.java


```
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPServer {

	public static void main(String[] args) throws IOException {
		int port = 999;
		int buffer_size = 1024;

		byte buffer[] = new byte[buffer_size];
		DatagramSocket ds = new DatagramSocket(port);
		while (true) {
			DatagramPacket p = new DatagramPacket(buffer, buffer.length);
			ds.receive(p);
			System.out.println(new String(p.getData(), 0, p.getLength()));
		}

	}

}
```

UDPClient.java

```
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;

public class UDPClient {

	public static void main(String[] args) throws IOException {
		int port = 999;
		InetAddress address = InetAddress.getByName("localhost");

		DatagramSocket socket = new DatagramSocket();

		for (int i = 0; i < 10; i++) {

			String date = new Date().toString();
			DatagramPacket packet = new DatagramPacket(date.getBytes(), date.getBytes().length, address, port);

			packet.setData(date.getBytes());
			socket.send(packet);

			sleep(1000);
		}

		socket.close();
	}

	private static void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
```

Ich hoffe es Hielf dir!!!


----------



## Big_Daddi (4. Aug 2009)

Also sprich ich muss zuerst wissen an welchen Port das Gerät die Daten schickt??
Ich glaub jetzt hats gerappelt. 

Wenn ich jetzt zb auf port 1500 stell dann bleibt er stehen. 
Jetzt mal sehn was mir die leute sagen, wohin die die daten senden.

DANKESCHON


----------



## Big_Daddi (13. Aug 2009)

Halli Hallo,

jetzt bin ichs schon wieder! Und zwar hänge ich jetzt an folgendem Problem:

ich sende einen String an ein Gerät, das funktioniert auch. Dann sendet das Gerät etwas zurück, das funktioniert auch. Hab ich mit Wireshark getestet. Es kommt auch das zurück was zurück kommen soll.
Jedoch bleibt mein Java-Programm also Eclipse vor udpreceive.receive(data); stehen
Hier der Codeausschnitt

```
byte buffer [] = new byte [100];
DatagramSocket udpreceive = new DatagramSocket();
DatagramPacket data = new DatagramPacket(buffer, buffer.length);
udpreceive.receive(data);
System.out.println(new String(data.getData(),0,data.getLength()));
```

Danke schon mal!


----------



## Geeeee (13. Aug 2009)

Bleibt er "vor" receive hängen oder in der Zeile.
Das erste wäre wirklich sehr komisch. Im zweiten Fall könnte es daran liegen, dass du deinem Socket keinen port gegeben hast.


----------



## Dissi (13. Aug 2009)

ist dein Ankommendes Packet evt kleiner als 100?


----------



## Big_Daddi (14. Aug 2009)

Guten Morgen,

@Geee:
Also ich hab einfach folgendes versucht. vor der receive Zeile einfach nen System.out.println() rein gesetzt, das geht auch soweit. Aber wenn ich es danach setze dann schreibt er mir es nicht aus, eben wie den String! Wireshark sagt dass die Daten an Port 49156 rein kommen und von Port 65363 kommen. Wie gebe ich denn eine Socket frei???

ja mein ankommendes Paket hat derzeit 30 bytes laut Wireshark. und das stimmt auch. Das ganze läuft so ich schicke eine Zeichenkette an das Gerät, das Gerät verarbeitet diese und schaut welche daten es mir schicken muss. Als Bsp ich schicke IPADDRESS dann sendet das Gerät mir eben seine ip-adresse zurück oder name oder sonstige variablen! 
Wie gesagt es kommt auch an aber das java kann irgendwie nicht verarbeiten??????
???:L???:L???:L


----------



## Geeeee (14. Aug 2009)

Dei Größe ist doch total egal. Hauptsache es kommt was. Wenn es mehr als 100 Bytes sind, wird abgeschnitten.
Wenn du dir sicher bist, dass dein Gerät auf 65363 zurücksendet, dann ergänze oben die Zeile:

```
DatagramSocket udpreceive = new DatagramSocket();
```
durch

```
DatagramSocket udpreceive = new DatagramSocket(65363);
```

Verstehe diese "Gerätverbindung" irgendwie immer noch nicht. Musst du überhaupt einen neuen Socket anlegen? Kann man nicht einfach den, der schon an das Gerät gesendet hat, verwenden? (Wie gesagt UDP-Erfahrungen was vor allem die Umsetzung angeht, sind bei mir nicht so ausgeprägt  )


----------



## Big_Daddi (14. Aug 2009)

Ja des stimmt schon, mir geht es auch nicht um die Größe. sondern ich möchte einfach nur mal dass mein Programm was mach! 

Das mit dem Port im DatagramSocket hab ich auch schon versucht! 
Des is ne gute Frage ob ich den gleichen nehmen kann oder nicht. Ich habs jetzt auch mal mit dem gleichen versucht aber der geht auch nicht wirklich. 

Kann es vlt. mit etwas außerhalb von Eclipse zu tun haben. Also mein LittleSnitch sagt, dass die Verbindungen von und zu der IP von dem Gerät frei sind also erlaubt sind!!!


----------



## Geeeee (14. Aug 2009)

So..hier nochmal ein einfaches Beispiel mit Hin- und Rückweg:
Dein "Gerät"

```
public class UDPMaster {

    public static void main(String[] args) throws IOException {
        byte[] code = new byte[100];
        DatagramSocket readerSocket = new DatagramSocket(1234);
        DatagramSocket senderSocket = new DatagramSocket();
        
        DatagramPacket packet = new DatagramPacket(code,code.length);
        readerSocket.receive(packet);
        
        
        System.out.println("got order: " + new String(code));
        String answer = "answer";
        
        packet = new DatagramPacket(answer.getBytes(),answer.getBytes().length, InetAddress.getLocalHost(), 1235);
        senderSocket.send(packet);
        
    }
    
}
```
Dein Rechner:

```
public class UDPSlave {
    
    public static void main(String[] args) throws IOException {
        byte[] incomingInformation = new byte[100];
        byte[] order = new String("do something").getBytes();
        InetAddress address = InetAddress.getLocalHost();
        DatagramSocket senderSocket = new DatagramSocket();
        DatagramSocket readerSocket = new DatagramSocket(1235);
        DatagramPacket packet = new DatagramPacket(order, order.length,address, 1234);
        senderSocket.send(packet);
        packet = new DatagramPacket(incomingInformation, incomingInformation.length);
        readerSocket.receive(packet);
        System.out.println("Got information: " + new String(packet.getData()));
    }

}
```
Ist nur auf die Schnelle getippt, aber funzt eigentlich. Musst nur noch die Ports anpassen. Soweit ich das jetzt getestet habe, geht ein Re-Use des Sockets bei UDP nicht (wg. dem nicht vorhandenen Zustand?).
Fänd es interessant zu erfahren, ob mein oben geschriebenes Beispiel so "UDP-konform" ist.


----------



## Big_Daddi (14. Aug 2009)

Da ist ja eigentlich das selbe wie ich habe. ;(

Naja das Problem mit dem Incoming Port ist dies, dass der sich anscheinend immer ändert. Also so sieht es zumindest im Wireshark aus. Somit kann ich ja den Port im Socket nicht angeben!


----------



## Geeeee (14. Aug 2009)

so.update:
Client:

```
public class UDPSlave {
    
    public static void main(String[] args) throws IOException {
        byte[] incomingInformation = new byte[100];
        byte[] order = new String("do something").getBytes();
        InetAddress address = InetAddress.getLocalHost();
        DatagramSocket senderSocket = new DatagramSocket();
        DatagramPacket packet = new DatagramPacket(order, order.length,address, 1234);
        senderSocket.send(packet);
        packet = new DatagramPacket(incomingInformation, incomingInformation.length);
        senderSocket.receive(packet);
        System.out.println("Got information: " + new String(packet.getData()));
    }

}
```
Gerät:

```
public class UDPMaster {

    public static void main(String[] args) throws IOException {
        byte[] code = new byte[100];
        DatagramSocket readerSocket = new DatagramSocket(1234);
        DatagramSocket senderSocket = new DatagramSocket();
        
        DatagramPacket packet = new DatagramPacket(code,code.length);
        readerSocket.receive(packet);
        
        
        System.out.println("got order: " + new String(code));
        String answer = "answer";
        
        packet = new DatagramPacket(answer.getBytes(),answer.getBytes().length, packet.getAddress(), packet.getPort());
        senderSocket.send(packet);
        
    }
    
}
```


----------



## Big_Daddi (14. Aug 2009)

Danke für die Hilfe, aber das funktioniert trotzdem nicht!

auf das Gerät habe ich keinen Einfluss!


----------



## Geeeee (14. Aug 2009)

Du machst doch gar nix mit dem Gerät...Nimm einfach nur den Slave code, mit dem passenden Port auf dem dein Gerät horcht und pack deine IPNACHRICHT drauf.


----------



## Big_Daddi (14. Aug 2009)

Der Code ist ja nur ein Ausschnitt von meinem Gesamtprogramm! 

Wie gesagt senden funktioniert aber der empfang eben nicht.


----------



## Geeeee (14. Aug 2009)

Dann zeig ich nochmal die Ausschnitte auf, weil evtl. hast du die kleine Änderung nicht gesehen:

```
DatagramSocket senderSocket = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(order, order.length, GERAET_IP , GERAET_PORT);
```
dann kannst du

```
// befehl senden
senderSocket.send(packet);
// antwort empfangen
byte[] incomingInformation = new byte[100];
packet = new DatagramPacket(incomingInformation, incomingInformation.length);
senderSocket.receive(packet);
```
Da ist dir der Port, von dem das Gerät zu deinem Rechner kommt total egal. Du musst eben nur wissen, auf welchem port du das Gerät ansprechen musst am Anfang (das klappt ja schon, hast du ja gesagt).
Du kannst das alles hintereinander weg so reinschreiben.


----------



## Big_Daddi (14. Aug 2009)

Also das gleiche hab ich jetzt mal versucht -> ohne erfolg!!!!

Wie gesagt send(); klappt aber receive(); bleibt er einfach stehen und wartet auf ein einkommendes Paket. Laut Wireshark kommt das ja auch aber das Javaprogramm frisst es nicht! 

Die receive() Methode frägt doch alle eingehenden ports ab oder??? Muss ich die Ports bei meinem PC irgendwie öffnen oder so????


----------



## Geeeee (14. Aug 2009)

Du könntest ja einfach mal bei senderSocket.receive einen breakpoint setzen und schauen, ob der localPort (also, der durch den die Verbindung auf Clientseite aufgemacht wurde) der gleiche ist, den du auch in Wireshark siehst.


----------



## Big_Daddi (14. Aug 2009)

Gute Idee! ...

senderSocket.getLocalPort();

Damit bekomm ich den gleichen Port der auch in WireShark steht. 

ich hab jetzt mal senderSocket.isConnected(); gemacht, aber da liefert er mir false zurück???????????


----------



## Geeeee (14. Aug 2009)

der Socket ist ja auch nur gebunden, wenn "was passiert". Der liefert bei mir auch immer false zurück. Würde wohl nur während des Sendens / Empfangens true sein.
Also nun ist das Problem wirklich sehr komisch. Wenn du da am Empfang hängst und wireshark sagt, dass da was kommt, dann muss es doch auch eingelesen werden. Ich bin verwirrt.


----------



## Big_Daddi (14. Aug 2009)

ich hab jetzt mal mit .connect(Addr., port); das nochmal versucht, bleibt aber trotzdem an der stelle stehen!

Ich verzeweifel langsam aber sicher!


----------



## Geeeee (14. Aug 2009)

Das brauchst du ja auch gar nicht.
Rezept für den einfachen Fall eines Befehls vom Client:

Zutaten:
1 DatagramSocket
1 InetAddress vom Server
1 Port vom Server
2 DatagramPackets (eins zum Senden und eins für den Empfang)
2 byte[] (Empfang / Senden)
Zubereitung:
1. Man nehme das eine byte[] und packe seinen Befehl hinein.
2. Man bereite das zweite byte[] mit einer beliebigen Größe vor.
3. Einstellen der InetAddress auf das Ziel.
4. Erstellen Sie nun einen DatagramSocket OHNE parameter.
5. Zum Senden des Befehls sollten Sie nun ein DatagramPacket-Objekt erstellen, dem Sie die Nachricht, Länge, InetAddress und Port mit auf dem Weg geben.
6. Die vorgefertigten Stücke mit Hilfe des DatagramSockets rausschicken
--- Nun kommt der komplizierterer Teil. Einige Köche scheitern an dieser Stelle  ---
7. Um eine Antwort zu erhalten, sollten sie nun ein zweiten DatagramPacket-Objekt erstellen, welches nur die Informationen enthält, in welches (vorbereitete) byte[] es schreiben soll und wieviel maximal beigefügt werden darf
8. Nun machen wir erneut Gebrauch von unserem DatagramSocket, mit dem wir schon erfolgreich unsere Nachricht rausgesendet haben. Mit Hilfe des gerade erzeugten DatagramPackets wird er in den LeseModus gesetzt.
9. Über das Ergebnis freuen.

Ist jetzt gerade mal irgendwie n bissl untechnischer geworden, aber überprüf bitte, ob du auch alles so gemacht hast.
Wenns noch immer net klappt, kannst du mir gerne deinen Source auch mal als PM schicken (gekürzte, ausführbare aber nicht funktionierende Version).
Oder bau dir selber einmal nach dem o.g. MasterBeispiel ein "Gerät-Mock"


----------



## Big_Daddi (14. Aug 2009)

JUHU es geht!!!

Es liegt an OSx. Jetzt geht es los dieses Problem zu finden!  ???:L

Unter Windows läuft es! ;(


----------



## HoaX (14. Aug 2009)

Firewall?


----------



## Big_Daddi (14. Aug 2009)

ist eigentlich aus!!!!!


----------

