# Single-threaded UDP



## Xeonkryptos (25. Nov 2012)

Hey Leute,

ich bin gerade dabei eine Client-Server-Kommunikation zu basteln. Diese muss über UDP ablaufen (gestellte Aufgabe) und serverseitig von einem Thread betrieben werden.

Das Verschicken der Nachrichten über die Verbindung zwischen Server und Client funktioniert problemlos.
Die Kommunikation von 2 Clients mit dem Server klappt auch noch einwandfrei.
Prinzipiell soll es eine Echo-Verbindung sein. Der Client schickt eine Nachricht und der Server antwortet.

Mein Problem ist es, wenn 3 oder mehrere Clients dazukommen und diese vom Server alle verarbeitet werden müssen. Ab 3 Clients werden die Nachrichten verschluckt bzw kommen nie an. Von geplanten 300 Requests kommen bei 3 Clienten 101 Responses zurück und wenn ich von 10 Clienten ausgehe, kommen von geplanten 1000 Requests nur 200 Responses. Der Server packt es nur allerhöchstens 2 Clienten in einem Thread zu verarbeiten.

Nun sollte der Server es aber schaffen, mit allen Clienten in Verbindung zu treten und diese zu verarbeiten, die Aufgabe dabei ist, der Server darf nur in einem Thread ablaufen!
Multithreaded habe ich keine Probleme beim Lösen der Aufgabe gehabt.
Ich habe diese Aufgabe auch ohne Probleme single-threaded in TCP gelöst. Hier gibt es die backlog-Funktion, die dabei hilfreich war, doch existiert diese bei UDP leider nicht und ich bin momentan ratlos, wie ich diese Aufgabe lösen soll. Ich kriege es nicht hin, dass der Server alle Pakete, zumindest die die nicht verloren gehen, welche wohl auf dem lokalen Rechner gering bis gar nicht vorhanden sind, empfängt und darauf eine Response zurückgibt.

Client (Teil: Senden von Nachrichten)

```
for (int i = 0; i < numberOfMessages; i++) {
				// Verbindung zum Server aufbauen
				con = new UdpSocket(localPort);

				// EchoPDU initialisieren
				EchoPDU pdu = new EchoPDU();

				// Letzter Request?
				if (i == numberOfMessages - 1) {
					pdu.setLastRequest(true);
				}

				// Echo-Request an Server senden
				con.send(InetAddress.getByName(remoteServerAddress),
						serverPort, (Object) pdu);

				EchoPDU recievedPdu = (EchoPDU) con.receive(timeout);

				// Transportverbindung abbauen
				con.close();

				// Denkzeit
				try {
					Thread.sleep(clientThinkTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
```
Die EchoPDU-Klasse ist einfach nur die serialisierbare Klasse, die zwischen Server und Client hin- und hergeschickt wird.
Die Variable "con" ist das Objekt, welches die DatagramSockets und -Packets enthält. Eigene Klasse, die ein vereinfachtes Senden und Empfangen ermöglicht. Es wird nichts weiteres gemacht, als die 
	
	
	
	





```
send
```
 und 
	
	
	
	





```
receive
```
-Methoden von DatagramSocket aufzurufen und eigenständig, intern zu verarbeiten.
Das ist mein Ansatz für den Client, bei dem maximal 2 Clients versorgt werden können.

Der Server sieht wie folgt aus:

```
while (true) {
			try {
				// Echo-Request entgegennehmen
				EchoPDU pdu = (EchoPDU) socket.receive(timeout);

				// Echo-Response senden
				socket.send(socket.getRemoteAddress(), socket.getRemotePort(),
						pdu);
			} catch (Exception e) {
				// ExceptionHandling
			}
		}
```
Das ist der Kern des Servers. Die Variable "socket" ist hier vom selben Typ wie die Variable "con" vom Client. Arbeitet also auf dieselbe Weise. Zuvor wird diese natürlich initialisiert! Der Server läuft im main-Thread!

Ich brauche nun Hilfe. Ich weiß nicht, wie ich es schaffe, dass der Server jede Anfrage der Clients verarbeitet und eine Antwort schickt, ohne das ein Client erst gar nicht zum Zuge kommt. Der Server muss hierbei single-threaded bleiben! Wie gesagt, bei TCP war dies durch den backlog der ServerSocket-Erzeugung möglich. So einen Ansatz oder etwas, dass auf eine ähnliche Weise funktioniert bzw mich auf den richtigen Weg führt, wäre schon sehr hilfreich.

Ich habe schon viel gegooglet und gesucht, doch kommen immer nur die einfachsten UDP-Server/-Clients zum Vorschein, bei denen ich keine Lösung meines Problems sehe.


----------



## trääät (25. Nov 2012)

gleich ob single oder multi threaded ... es liegt nun mal in der natur von UDP das halt nicht garantiert wird in welcher reihen folge daten ankommen oder ob diese überhaupt ankommen ...
und ich gehe einfach mal von aus das bei der single-thread verarbeitung irgendwelche timeouts oder flood-limits erreicht werden und dann das system einfach anfängt pakete zu droppen die so beim multi-threaded system wenigstens noch die chance haben verarbeitet zu werden und im RAM zu landen ...

auch wenn es theoretisch möglich sein müsste kann es auf grund UDP nicht 100% garantiert werden ... und wer dann noch auf die idee kommt sowas bewusst single-threaded zu machen und damit wissend das dropping in kauf nimmt ... naja ... als lern-aufgabe vielleicht damit man es mal erlebt hat ... aber ansonsten praktisch nicht von bedeutung ...


----------



## vimar (27. Nov 2012)

bevor ichs garnicht schreibe schreib ichs lieber, vllt einfach mal den empfangspuffer von der netzwerkkarte hochschrauben und die tcpwindowsize höher setzn


----------

