# TCP and UDP



## lumo (8. Nov 2011)

hallo,

ich habe eine anwendung die die sicheren daten per tcp verteilt (login/logout und rechtesystem)
zum versenden der daten (bilder etc) möchte ich aber udp verwenden, da das doch einiges flotter geht.

meine frage ist hier nun...

TCP kommt ohne konfiguration des routers (beim client) rein/raus (durch testen rausgefunden.
wird das mit udp auch so sein? den bei udp meldet sich ja keiner an bzw baut keiner eine bestehende verbindung auf (router kann also keinen request für einen login oder ähnliches erkennen)

ich würde nämlich gerne vermeiden, dass der user irgendwelche ports weiterleiten muss...

- ich hatte mir anfangs über sowas gar keinen kopf gemacht - aber jetzt wo ich sehe, dass es mit tcp funktioniert wäre es fein, wenn es mit udp auch klappt...

was dann auch noch so eine frage ist... der server soll einen port haben wo er udp sendet/empfängt
der client auch, -> muss ich in meinem server eine liste der ports für die clients speichern, kann aber ALLE clients über einen port handeln oder wird das dann langsamer??

danke schon mal
lumo


----------



## nillehammer (8. Nov 2011)

Ein Router arbeitet auf IP-Ebende. Von TCP und UDP weiß er nichts, ist im auch egal. TCP und UDP setzen auf IP auf. Wenn's also über TCP funktioniert, dann funktionierts auch über UDP. Falls nicht, liegt es zumindest nicht am Router.


----------



## nillehammer (8. Nov 2011)

> -> muss ich in meinem server eine liste der ports für die clients speichern, kann aber ALLE clients über einen port handeln oder wird das dann langsamer??


Überleg mal, wie es bei Hardcore-WebSerern wie google ist. Die lauschen alle auf einem einzigen Port. Nämlich 80. Es wird dadurch also nicht langsamer. Und genau genommen speicherst Du keine Liste der Ports der Clients, sondern hast für jeden Client ein Socketobjekt, über das Du mit ihm kommunizierst.

Edit:// Das stimmt natürlich nur bei TCP. Bei UDP hast Du natürlich Recht...


----------



## lumo (8. Nov 2011)

Ich hab mir schon das eine oder andere udp Beispiel angeschaut; hast du ein besonders gutes für udp? Mein tcp Server läuft nämlich schon bestens...


----------



## nillehammer (8. Nov 2011)

> ich würde nämlich gerne vermeiden, dass der user irgendwelche ports weiterleiten muss...


Ahh, Du meinst also nicht das reine Routing sondern noch sowas wie NAT oder Firewalling? Beim Standardfall (User sitzt hinter DSL-Router und will sich mit Server im Internet verbinden) muss man eigentlich nichts machen. Es sei denn, eine evtl. laufende Firewall ist vorher extrem restriktiv konfiguriert worden. Dann muss ggf. der entspr. UDP-Port für ausgehende Verbindungen freigeschaltet werden.

Wenn Du aber etwas implementierst, wobei von außen auf einen Server hinter dem DSL-Router zugegriffen werden muss (also praktisch die entgegengesetzte Richtung), dann muss der User den entspr. Port auf seinen internen Rechner forwarden.

Für normale Kommunikation reicht aber eigentlich die eine vom User/Client initiierte Verbindung zum Server. Man muss nicht sowas wie einen "Rückkanal" aufmachen.


----------



## nillehammer (8. Nov 2011)

> zum versenden der daten (bilder etc) möchte ich aber udp verwenden, da das doch einiges flotter geht.


Für Deinen genannten Anwendungsfall stimmt das nur bedingt, auf jeden Fall nicht so, dass Du einen Unterschied merkst. UDP ist effizient, wenn es um das Versenden kleinster Pakete geht, bei denen Verbindungshandling und Quittierung egal ist. Bei allem, was ab wenigen kilobytes losgeht, ist TCP definitiv die bessere Wahl.


----------



## nillehammer (8. Nov 2011)

> hast du ein besonders gutes für udp?


Leider nein. Für mehr als ein einfaches echo response habe ich udp noch nie benutzt.


----------



## lumo (8. Nov 2011)

Ok, also dann wird up nichts bringen, dann werd ich den tcp broadcast wohl umschreiben müssen dass er nicht blockiert, bzw nicht wartet bis die erste übertragung fertig is bevor er die nächste sendet -> eigener runnable für jeden client??


----------



## nillehammer (8. Nov 2011)

> -> eigener runnable für jeden client??


Ja, evtl. Nutzung von Pools usw. Aber an dieser Stelle muss ich aussteigen. Da sind meine praktischen Erfahrungen ehrlich gesagt doch sehr begrenzt.


----------



## lumo (8. Nov 2011)

connection pool davon hab ich schon gelesen, wusste aber erstmal nicht ob ich sowas brauche... scheint mir aber jetzt doch der fall zu sein 

err - kümmert sich dieses pool dann darum dass nix blockiert? oder hält der nur die infos der connections... sowas hab ich mämlich schon selbst geschrieben...


----------



## Nightmares (8. Nov 2011)

Ansonsten gibts noch NIO als nicht blockierende Alternative. Für NIO ist aber einiges an einarbeiten erfordert oder du guckst dir ein Framework an, welches darauf aufbaut wie z.B. Apache MINA, Netty und Co.


----------



## lumo (8. Nov 2011)

Also ich verwende schon nonblocking sockets Aber meine Broadcast Funktion sieht so aus:

pseudocode:


```
public void broadcast(string msg){
for (i=0, i<getconnections().size();i++ {
Connection conn = getconnections().get(i);
conn.send(msg);
}
}
```

jetzt müsste ich das umschreiben so dass es nicht mehr hintereinander abgearbeitet wird, sondern parallel

irgendwas in die art:

```
public void broadcast(String msg){
		System.out.print("broadcasting...");
		ExecutorService executor = Executors.newFixedThreadPool(10); // max 10 threads...
		for (i=0, i<getconnections().size();i++ {
			Connection conn = getconnections().get(i);
			Runnable worker = SendRunnable(conn, msg){
			executor.execute(worker);
		}
		// This will make the executor accept no new threads
		// and finish all existing threads in the queue
		executor.shutdown();
		// Wait until all threads are finish
		while (!executor.isTerminated()) {
		}
		System.out.println("done!");
}
```


----------



## Nightmares (8. Nov 2011)

Bau dir eine Klasse die Runnable implementiert derer du per Konstruktor deinen Socket und die Daten übergibts. Dann nimmst du einen Thread Pool Executor und fügst dem die Runnables mittels .execute(Runnable r) hinzu. Dieser arbeitet die dann so schnell er kann ab. Wenn deine Sockets aber nicht blocken musst du bedenken, dass wenn nicht alle Daten direkt geschrieben wurden du den Rest deiner Buffer auch noch schreiben musst. Denk mal lieber über NIO nach wenn du nicht blockenden IO möchtest oder darüber für jede Verbindung einen Thread zu haben der sich nur um die Verbindung kümmert und seine eingehenden Daten in eine Warteschlange schreibt und seine Ausgehenden aus einer Warteschlange nimmt. (Standard Thread-IO Ansatz, ein Thread pro Verbindung der sich nur um diese kümmert.)


----------



## lumo (8. Nov 2011)

Das mit dem runnable steht ja so in meinem Code; ein thread pro conection ist nicht skalierbar, hoste ich 10,100,1000 der Server auf einem pc wird das derb, mit je x Clients und x threads ; also wenn auf einem Server dann 64 Klienten sein können dann hatte ich schon bei 10 Servern 640threads
Sowas klappt super auf einer GPU mit 640 Kernen aber nicht auf einer CPU mit 1-16 kernen(virtuell)


----------



## lumo (8. Nov 2011)

Aja, ich verwende xsocket


----------



## Nightmares (8. Nov 2011)

Ein Thread pro Connection ist unter Windows nicht skalierbar. Unter Linux kein Problem. Ich hab außerdem nicht gesagt das es gut ist. Ich benutze auch nur noch NIO wenn ich in Java programmiere allerdings hab ich mir selber was geschrieben, weil ich a) nen eigenes Protokoll brauche, b) SSL und c) noch ein paar andere Dinge die mit den Frameworks nicht so ganz ohne weiteres gehen.


----------



## irgendjemand (9. Nov 2011)

wenn du willst das sich ein server durch einen router mit einem client via UDP verbinden kann ... dann google mal nach UDP HOLE PUNCHING
der sinn dahinter : der client sendet ausgehende udp-pakete über einen bestimmten port an eine bestimmte adresse ... und wenn jetzt von dieser adresse auf diesem port wieder udp-pakete zurück kommen weis der router anhand der NAT-tabelle das dies eine UDP-Session ist und leitet die daten weiter ...
genau so funktioniert das bei allen udp-diensten wie z.b. skype , teamspeak , etc ...

die genauen daten kannst du dabei über die TCP-verbindung aushandeln


----------



## lumo (9. Nov 2011)

also das NO_DELAY hat schon mal was gebrahcht... jetzt ists nicht mehr 200 sondern nur noch 100 )


----------



## lumo (9. Nov 2011)

irgendjemand hat gesagt.:


> wenn du willst das sich ein server durch einen router mit einem client via UDP verbinden kann ... dann google mal nach UDP HOLE PUNCHING
> der sinn dahinter : der client sendet ausgehende udp-pakete über einen bestimmten port an eine bestimmte adresse ... und wenn jetzt von dieser adresse auf diesem port wieder udp-pakete zurück kommen weis der router anhand der NAT-tabelle das dies eine UDP-Session ist und leitet die daten weiter ...
> genau so funktioniert das bei allen udp-diensten wie z.b. skype , teamspeak , etc ...
> 
> die genauen daten kannst du dabei über die TCP-verbindung aushandeln



gut, dann mach ich das so


----------

