Discussion:
Mehrere Socketverbindungen von einem Client zum Server
(zu alt für eine Antwort)
Remo Hartwig
2007-01-20 09:29:17 UTC
Permalink
Hallo,

gibt es in Java was, womit ich mehrere Verbindungen von einem Client aus
zu einem Server oeffnen und an die richtige Stelle Daten senden kann?
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem
Host existiert, ohne den Port zu aendern.
Wenn es hier nichts gibt, wie gehe ich sonst an die Sache ran?


|--------|
| Socket |\
| | \ |--------------|
| Socket |--\| ServerSocket |
| | /|--------------|
| | / Server
| Socket |/ (10.0.0.2:5000)
|--------|
Client
(10.0.0.1:5000)

Viele Gruesse
Remo
Carsten Dimmek
2007-01-20 09:50:22 UTC
Permalink
Post by Remo Hartwig
Hallo,
gibt es in Java was, womit ich mehrere Verbindungen von einem Client aus
zu einem Server oeffnen und an die richtige Stelle Daten senden kann?
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem
Host existiert, ohne den Port zu aendern.
Wenn es hier nichts gibt, wie gehe ich sonst an die Sache ran?
|--------|
| Socket |\
| | \ |--------------|
| Socket |--\| ServerSocket |
| | /|--------------|
| | / Server
| Socket |/ (10.0.0.2:5000)
|--------|
Client
(10.0.0.1:5000)
Viele Gruesse
Remo
Hallo, das geht meines Wissens nicht, auch mit anderen
Programmiersprachen nicht. Ein Socket muss immer eindeutig sein. Ein
Socket wird eindeutig durch den Clienthost+Port und dem Serverhost+Port.
Sonst kann die Verbindung nicht vom Betriebssystem verwaltet werden.
Du müsstes das sonst wie bei FTP machen, dass der Server einen zweiten
Socket für den Client unter einem anderen Port aufmacht.

Gruss,
Carsten
Ralf Ullrich
2007-01-20 10:22:39 UTC
Permalink
Post by Remo Hartwig
gibt es in Java was, womit ich mehrere Verbindungen von einem Client aus
zu einem Server oeffnen und an die richtige Stelle Daten senden kann?
Das ist ja die eigentliche Aufgabe von Socket und ServerSocket, wobei du
deine mehreren Verbindungen auf Server-Seite dadurch auseinander hältst,
dass du pro angenommener Verbindung (siehe ServerSocket#accept()) einen
Socket erhältst. Der eigentliche Datenaustausch auf den Verbindungen
erfolgt ja dann zwischen clientseitigem Socket-Exemplar und serverseitigem
Socket-Exemplar, also in einer 1:1 Relation.
Post by Remo Hartwig
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem Host
existiert, ohne den Port zu aendern.
ServerSocket hätte immer nur einen Port und eigentlich könntest du den
Client seinen Port einfach frei wählen lassen und damit für jede
Verbindung einen eigenen. (Bedenke: es gibt pro Verbindung zwei
voneinander unabhängige Ports! Je einen pro Client und Server. Nur der
Server-Port muss normalerweise festgeschrieben werden, und das auch nur,
damit der Server ansprechbar ist.) So machen es alle anderen und sind
damit zufrieden und fertig.

Also ist die Frage, warum musst du es unbedingt komplizieren? Wieso
glaubst du, den Client-Port fix vorgeben zu müssen? Welches Problem
versuchst du damit zu lösen?

Ein Problem mit der Port-Vorgabe am Client ist, dass dann nur noch genau
ein solcher Socket am Client geöffnet werden kann, selbst wenn dieser in
einem anderen Prozess geöffnet wurde. Das Betriebssystem, kann die
Verbindungen auf Netzwerkebene nämlich selbst nur anhand des
(Socket-)Datensatzes [Client-Adresse, Client-Port, Server-Adresse,
Server-Port] auseinanderhalten. Würde das OS zwei identische Sockets
erlauben, wüsste es selbst nicht mehr, welchem Prozess es ankommende Daten
weitergeben sollte.
Post by Remo Hartwig
Wenn es hier nichts gibt, wie gehe ich sonst an die Sache ran?
Wie gesagt, normalerweise löst sich das Problem von selbst, wenn du den
Client-Port frei wählbar machst (sprich in Java, bei der Erzeugung des
Client-Sockets als Port die 0 angibst). So funktioniert es für sicherlich
über 99,99% der verbindungsorientierten Netzwerkanwendungen, du müsstest
also schon sehr gute Gründe haben es anders machen zu wollen.

Alternativ wäre es möglich, sich von

a) Verbindungsorientierung zu verabschieden, und DatagramSockets zu
verwenden, oder sich von

b) Verbindungsorientierung und gerichteter Übertragung zu verabschieden,
und MulticastSockets zu verwenden.

In beiden Fällen musst du die Funktionalität, von der du dich zunächst
verabschiedet hast, evtl. selbst wieder nachbauen, sofern dies für deine
Anwendung erforderlich ist. (Ist meist der Fall!) Es wird also sehr
kompliziert.

Aber ich kann dir nur nochmals eindringlich raten, deine Motivation den
Client-Port festzuschreiben zu hinterfragen. Dies ist in der Regel nicht
nötig, und ich würde doch zugern wissen, welche triftigen Gründe du dafür
zu haben glaubst.

cu
Remo Hartwig
2007-01-21 17:14:03 UTC
Permalink
...
Post by Ralf Ullrich
Post by Remo Hartwig
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem
Host existiert, ohne den Port zu aendern.
ServerSocket hätte immer nur einen Port und eigentlich könntest du den
Client seinen Port einfach frei wählen lassen und damit für jede
Verbindung einen eigenen. (Bedenke: es gibt pro Verbindung zwei
voneinander unabhängige Ports! Je einen pro Client und Server. Nur der
Server-Port muss normalerweise festgeschrieben werden, und das auch nur,
damit der Server ansprechbar ist.) So machen es alle anderen und sind
damit zufrieden und fertig.
Ok, ich habe mal wieder einfach zu falsch gefragt, die anderen Antworter
vermuteten wohl, worauf es hinaus laeuft.

Ich nehme einfach mal den Serverport weiter auf 5000.

Bleibe ich also bei normal new Socket(serverip, 5000) ohne auf
localhost:0 umzuleiten.

Wie realisiere ich folgendes?


10.0.0.1:5000\
\
10.0.0.2:5000--\ 1.2.3.4 (NAT, FW(5000 offen) ------ Server(5000)
/ /
10.0.0.3:5000/ 5.6.7.8:5000/

5.6.7.8 laeuft normal.
Wenn sich einer hinter 1.2.3.4 anmeldet laeufts weiter normal.
Wenn ein zweiter aus dem lokalen Netz auf den oeffentlichen Server will,
bricht alles kaputt.

Beispiel 5.6.7.8, 10.0.0.1 und 10.0.0.2 wollen gegeneinander Spielen,
oder irgendwelche Daten austauschen oder...

Bekomme ich sowas auf flach Java geloest?
Was benoetige ich ansonsten?

Gruesse
Remo
Ralf Ullrich
2007-01-21 17:55:17 UTC
Permalink
Post by Remo Hartwig
Ich nehme einfach mal den Serverport weiter auf 5000.
Bleibe ich also bei normal new Socket(serverip, 5000) ohne auf localhost:0
umzuleiten.
Wie realisiere ich folgendes?
10.0.0.1:5000\
\
10.0.0.2:5000--\ 1.2.3.4 (NAT, FW(5000 offen) ------ Server(5000)
/ /
10.0.0.3:5000/ 5.6.7.8:5000/
5.6.7.8 laeuft normal.
Wenn sich einer hinter 1.2.3.4 anmeldet laeufts weiter normal.
Wenn ein zweiter aus dem lokalen Netz auf den oeffentlichen Server will,
bricht alles kaputt.
Beispiel 5.6.7.8, 10.0.0.1 und 10.0.0.2 wollen gegeneinander Spielen, oder
irgendwelche Daten austauschen oder...
Bekomme ich sowas auf flach Java geloest?
Was benoetige ich ansonsten?
Ich glaube du hast da immer noch einige Missverständnisse auf deiner Seite
bezüglich der Begriffe "Server-Port" und "Client-Port" (bzw. local port)
auszuräumen.

Also nehmen wir den Server mal als Blackbox an und kümmern uns erst mal
nicht weiter um ihn. Die NAT/FW hat, wie du ja schon schreibst eine Regel
für den Port 5000, die ich nun auf tcp-5000-outgoing präzisieren möchte!

10.0.0.1 (=C1) und 10.0.0.2 (=C2) wollen also mit dem Server 5.6.7.8 (=S)
gegeneinander spielen. Es passiert folgendes:

1. C1 meldet sich an:

Socket s = new Socket(serverip, 5000);

Im Gegensatz zu deinem Bild sieht die Verbindung nun so aus:

Für C1:
10.0.0.1:ephemeral1 <--> serverip:5000

Die NAT/FW macht nun eine Umsetzung:

10.0.0.1:ephemeral1 == 1.2.3.4:ephemeral2 <--> serverip, 5000

Am Server scheint nur die NAT Adresse zu existieren, er sieht diese
Verbindung:

1.2.3.4:ephemeral2 <--> serverip, 5000

Soweit, kein Problem.

2. C2 meldet sich an:

Socket s = new Socket(serverip, 5000);

Weiterhin im Gegensatz zu deinem Bild sehen die Verbindungen nun so aus:

Für C1 und C2:
10.0.0.1:ephemeral1 <--> serverip:5000
10.0.0.2:ephemeral3 <--> serverip:5000

Die NAT/FW macht nun zwei Umsetzungen:

10.0.0.1:ephemeral1 == 1.2.3.4:ephemeral2 <--> serverip, 5000
10.0.0.2:ephemeral3 == 1.2.3.4:ephemeral4 <--> serverip, 5000

Am Server scheint nur die NAT Adresse zu existieren, er sieht diese
Verbindungen:

1.2.3.4:ephemeral2 <--> serverip, 5000
1.2.3.4:ephemeral4 <--> serverip, 5000


Alle erwähnten clientseitigen Ports sind sogenannte ephemeral ports, also
zufällig gewählte Ports (und damit in der Regel !=5000). Für diese gilt:

a) Da C1 und C2 verschiedene Hosts sind, könnten ephemeral1 und ephemeral3
gleich sein. Da sich aber die Adressen unterscheiden, kann die NAT/FW sie
auseinander halten.

b) ephemeral2 und ephemeral4 werden von der NAT/FW vergeben. Diese
garantiert, dass sie verschieden sind. Da der Server nur diese Ports
kennt, kann auch er die Verbindungen problemlos auseinander halten.

c) ephemeral2 kann von der NAT/FW gleich ephemeral1 gewählt werden, muss
aber nicht. Die NAT/FW wird das nur machen, wenn ephemeral2 auf der
NAT-Adresse 1.2.3.4 gerade nicht in Gebrauch ist.

d) wie c) für ephemeral4 und ephemeral3.



Du siehst, es gibt eigentlich keinerlei Kollisionen dabei. C1, C2 und S
können problemlos miteinander spielen. Aber es gibt natürlich nur jeweils
die Kommunikation zwischen C1 und S und C2 und S. Wollen C1 und C2
Datenaustauschen, müssen sie das über das Spiele-Protokoll indirekt über
den Server S tun.

Probleme kann es erst geben, wenn du an deiner NAT auf Port 5000 incoming
Traffic haben willst, aber das ist eine andere Geschichte.


Im Übrigen hat das alles nichts mit Java im Speziellen zu tun, sondern nur
allgemein mit Netzwerk, TCP/IP und NAT/FW.

cu
Remo Hartwig
2007-01-21 18:35:04 UTC
Permalink
Ralf Ullrich schrieb:
...

Danke erstmal. Das muss ich morgen gleich mal testen. Dann bin ich in
der C1/C2..-Umgebung.
Es kam zum haengen von Server, wenn C1 und C2 gleichzeitig wollten,
nicht aber, wenn verschiedene externe und entweder C1 oder C2.
Mir schien es jedenfalls, dass Server C1 und C2 nicht auseinander halten
konnte.
Am NAT wird das Problem mit grosser Wahrscheinlichkeit nicht liegen.
Waere ja schoen, wenn grundsaetzlich alles IO ist.
Ich melde mich diesbezueglich nochmal.

Da faellt mir ein... Was ist, wenn ein SOCKS-Proxy zwischenhaengt, also
INTERN-SOCKS-EXTERN


Vielleicht komm ich an die iptables des Routers ran und find irgendwas wie:
iptables -t nat -A PREROUTING -i $LAN -p tcp --dport $ALLESOCKSPORTS -j
DNAT --to $SOCKS_SERVER:$SOCKS_PORT
und aehnliches von $INTERNET.

Koennte sowas Auswirkungen haben?

P.S.: 5.6.7.8 sollte einen externen Clienten darstellen.

Danke und Gruesse
Remo
Florian Weimer
2007-01-21 19:50:10 UTC
Permalink
Post by Remo Hartwig
10.0.0.1:5000\
\
10.0.0.2:5000--\ 1.2.3.4 (NAT, FW(5000 offen) ------ Server(5000)
/ /
10.0.0.3:5000/ 5.6.7.8:5000/
5.6.7.8 laeuft normal.
Wenn sich einer hinter 1.2.3.4 anmeldet laeufts weiter normal.
Wenn ein zweiter aus dem lokalen Netz auf den oeffentlichen Server
will, bricht alles kaputt.
Dann ist der Fehler nicht auf der Server-Seite, sondern liegt daran,
daß das NAT-Device kaputt ist (im Fall TCP und meinetwegen auch SCTP),
oder das Anwendungsprotokoll nicht unterstützt (UDP).
Marian Aldenhövel
2007-01-22 07:41:12 UTC
Permalink
Hallo,
Post by Florian Weimer
Dann ist der Fehler nicht auf der Server-Seite, sondern liegt daran,
daß das NAT-Device kaputt ist
Oder der Server davon ausgeht, daß er Clients an der IP-Adresse unterscheiden
kann. Also zum Beispiel Sessions verwaltet, und dabei die IP-Adresse als
Kriterium heranzieht.

Dann wäre das Problem vom genauen Netzwerksetup unabhängig und in der
Implementation der Serverlogik zu suchen.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Thomas Enzinger
2007-01-20 10:22:27 UTC
Permalink
Post by Remo Hartwig
Hallo,
gibt es in Java was, womit ich mehrere Verbindungen von einem Client aus
zu einem Server oeffnen und an die richtige Stelle Daten senden kann?
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem
Host existiert, ohne den Port zu aendern.
Wenn es hier nichts gibt, wie gehe ich sonst an die Sache ran?
|--------|
| Socket |\
| | \ |--------------|
| Socket |--\| ServerSocket |
| | /|--------------|
| | / Server
| Socket |/ (10.0.0.2:5000)
|--------|
Client
(10.0.0.1:5000)
Wieso, möchtest du von einem Port mehrere Verbindungen zu einem Server
aufbauen? Mittels Socket -- ServerSocket ist das nicht möglich. Hier für
gibt es doch sehr viele freie Ports auf deinem OS ;-)

Noch ein kleines Zitat "Um die Server voneinander unterscheiden zu
können, gibt es ein weiteres Adressmerkmal, die Port-Nummer. Sie wird
oberhalb von IP auf der Ebene des Transportprotokolls definiert (also in
TCP bzw. UDP) und gibt die Server-Anwendung an, mit der ein Client
kommunizieren will. Port-Nummern sind positive Ganzzahlen im Bereich von
0 bis 65535. Port-Nummern im Bereich von 0 bis 1023 sind für Anwendungen
mit Superuser-Rechten reserviert. Jeder Servertyp hat seine eigene
Port-Nummer, viele davon sind zu Quasi-Standards geworden. So läuft
beispielsweise ein SMTP-Server meist auf Port 25, ein FTP-Server auf
Port 21 und ein HTTP-Server auf Port 80. Tabelle 45.2 gibt eine
Übersicht der auf den meisten UNIX-Systemen verfügbaren Server und ihrer
Port-Nummern."
Quelle: Handbuch der Java-Programmierung, 4. Auflage, Addison Wesley,
http://www.javabuch.de

Mfg,
Thomas
Florian Weimer
2007-01-20 11:06:42 UTC
Permalink
Post by Remo Hartwig
In der Art Socket<-->ServerSocket, nur dass Socket mehrfach auf einem
Host existiert, ohne den Port zu aendern.
Das geht natürlich in gewissem Sinne, praktisch jeder Webserver macht
das so.
Post by Remo Hartwig
Wenn es hier nichts gibt, wie gehe ich sonst an die Sache ran?
|--------|
| Socket |\
| | \ |--------------|
| Socket |--\| ServerSocket |
| | /|--------------|
| | / Server
| Socket |/ (10.0.0.2:5000)
|--------|
Client
(10.0.0.1:5000)
Mit UDP läßt sich sich das 1:1 abbilden, mit TCP natürlich nicht. Es
gibt aber Ansätze wie Sand am Meer, etwas ähnliches bereitzustellen
(jeder Applikationsserver muß das unterstützen).
Remo Hartwig
2007-01-21 17:14:27 UTC
Permalink
Post by Florian Weimer
Mit UDP läßt sich sich das 1:1 abbilden, mit TCP natürlich nicht. Es
gibt aber Ansätze wie Sand am Meer, etwas ähnliches bereitzustellen
(jeder Applikationsserver muß das unterstützen).
Haettest Du da eine suchbare Wortgruppe parat, um einige Ansaetze zu finden?

Gruesse
Remo
Remo Hartwig
2007-01-22 20:35:24 UTC
Permalink
Hallo miteinander,

ich konnte im heutigen Netz den Fehler nicht nachvollziehen.
Das Problem besteht aber weiterhin in einem anderen Netz.
Ich versuche mal herauszufinden, wie dort die Anbindung des lokalen
Netzes an die Aussenwelt erfolgt.

Allen vielen Dank.
Remo

Loading...