Frage zum Verhalten von SocketChannel.write(.)

Status
Nicht offen für weitere Antworten.

kaesebrot

Mitglied
Hi,

ich bin gerade dabei einen nonblocking-Server zu implementieren und setze gerade das Versenden von Nachrichten um.
Die Daten die ich versenden möchte stelle ich in einem ByteBuffer bereit und übergebe diesen dann an den SocketChannel mittels der write-Methode.
Da der SocketChannel nonblocking ist kann es laut Doku sein, daß nicht der gesamte Buffer versendet (bzw. in den Socketbuffer kopiert) wird bevor der Methodenaufruf abgeschlossen wird. Dies ist im Speziellen auch der Fall, wenn der Channel bereit für's schreiben ist.

Meine Fragen hierzu:

1. Gehe ich richtig in der Annahme, daß die restlichen Daten auch noch versendet werden sobald der Channel dafür bereit ist
2. Ist weiterhin richtig, daß auf den gleichen Puffer zugegriffen wird

Ich hoffe der 1. Punkt stimmt :) Falls der 2. Punkt auch stimmen sollte bedeutet das, daß ich für jeden Versand einen neuen Puffer reservieren muß, da ich ja nicht sicher sein kann, ob der alte Inhalt noch benötigt wird.

Gibt es irgendwo eine Art Referenz-Implementierung für einen nonblocking Server. Ich habe bisher nur relativ primitive Beispiele finden können.


viele Grüße,
Käse
 
T

tuxedo

Gast
Nein, falsche Annahme. Der write() aufruf terminiert. Du kannst dann anschließend mit buffer.remaining() schauen wieviel noch gesendet werden muss.

Hab das bei mit in einer while-schleife gelöst:

Code:
while (buf.remaining()>0) {
socketChannel.write(buf);
}

Damit geht's. Allerdings stellt sich mir die Frage: Gibt es einen Fall in dem das das System blockieren kann, weil gar nie was gesendet werden kann?

Laut Doku tritt das "nicht senden können" auf, wenn der TX-BUffer auf Netzwerkebene "voll" ist und nicht noch mehr reingesteckt werden kann. Man muss da dann einfach "warten" bis wieder Platz ist und es nchmal versuchen.

- Alex
 

kaesebrot

Mitglied
Hi,

ich habe mir den Abschnitt in der Doku nochmal genau durchgelesen und du hast recht. Das Verhalten ist sinnig so. Ich werde aber warscheinlich nicht die Lösung mit der while-Schleife nehmen sondern den verbleibenden Buffer schreiben, sobald ich wieder signalisiert bekomme, daß der channel beschreibbar ist.

danke für deine Hilfe.


viele Grüße,
Käse
 

kaesebrot

Mitglied
Hi,

das "Signal" bekomme ich mittels eines Selectors.

ich habe es gestern abend wie oben angedeutet erfolgreich implementieren können.



viele Grüße,
Käse
 
T

tuxedo

Gast
Der Selector sagt dir doch aber nicht ob im Puffer auf Netzwerk/OS Ebene wieder Platz ist?

Wenn du "schreiben" willst, setzt du den entsprechenden "op interest" auf dem entsprechenden Key.
Dann kommt das Signal zum schreiben auf dem SocketChannel. Und wenn es dann beim schreiben nicht schnell genug geht (netzwerk sendepuffer voll), dann hast du buf.remaining()>0.

Wenn du jetzt auf einen weiteren Schreibbefehl erst wartest, dann verzögert sich das senden unnötig. Weil i.d.R. dauerts bis zum nächsten Schreibvorgang länger, als bis der Sendepuffer geleert wird. D.h. mit einer while() schleife bist du da i.d.R. besser dran.

- Alex
 

kaesebrot

Mitglied
Hi,

du hast recht, evtl. könnte ich die Daten für einen Client schneller verschicken, jedoch geht das dann auf Kosten der anderen Clients. Die Zeit die ich in der While-Schleife warte würde, wird somit verwendet um die anderen Clients abzuarbeiten.

Hast du weitergehende Informationen zu diesem Thema?


viele Grüße,
Käse
 
T

tuxedo

Gast
Nein, hab leider keine weiteren.

Zur "Wartezeit":

Ja, in der Tat muss auch bei der While-Schleife gewartet werden. Aber ich denke man kann davon ausgehen, dass die wartezeit bis wieder Platz im Ausgangspuffer bedeutend kleiner ist, als die Zeit die vergeht, bis ein neuer "write" interest auf dem entsprechenden key gesetzt ist. Und "bedeutend" heisst bei mir > Faktor 2. Gemessen hab ich's noch nicht. Ist auch etwas schwer zu messen. Denn es kommt bei mir, selbst wenn ich meinen Server mit >1000 Clients "stresse", die alle so schnell und so viel wie Möglich Daten an den Server schicken, verdammt selten vor.

Noch was hierzu:0
>> Die Zeit die ich in der While-Schleife warte würde, wird somit verwendet um die anderen Clients abzuarbeiten.

In unterschiedlichen Quellen im Netz findet man an vielen Stellen den Hinweis/Tipp, dass man nur mit einem einzigen Thread "senden" soll. Alles andere führt zu Synchronisationsproblemen und damit auch zu Performanceproblemen.
Und wenn man sich an den Ratschlag hält und nur in einem Thread sendet, dann hat man auf Client-Seite nach wie vor das "Problem", dass wenn der Sendepuffer voll ist, ich warten muss bis wieder Platz ist. Da hilft es dann auch nicht "keine while schleife" zu benutzen und mit dem nächsten Paket fortzufahren.
Höchstens auf Serverseite _könnte_ es _eventuell_ was bringen.

Werde versuchen das mal zu messen...

Gruß
Alex
 
G

Guest

Gast
Hi,

alex0801 hat gesagt.:
In unterschiedlichen Quellen im Netz findet man an vielen Stellen den Hinweis/Tipp, dass man nur mit einem einzigen Thread "senden" soll. Alles andere führt zu Synchronisationsproblemen und damit auch zu Performanceproblemen.
D.h. wenn ich zig Clients auf einem Server habe und eine Nachricht an alle verschicken will, bin ich gezwungen Client für Client abzuarbeiten? Kannst du mir evtl. einen Link geben, wo darauf hingewiesen wird? (Ansonsten suche ich auch heute abend allein danach, hab nur im mom. keine Zeit)

alex0801 hat gesagt.:
Und wenn man sich an den Ratschlag hält und nur in einem Thread sendet, dann hat man auf Client-Seite nach wie vor das "Problem", dass wenn der Sendepuffer voll ist, ich warten muss bis wieder Platz ist. Da hilft es dann auch nicht "keine while schleife" zu benutzen und mit dem nächsten Paket fortzufahren.
Höchstens auf Serverseite _könnte_ es _eventuell_ was bringen.
Hmm.. mehrere Clients gibts es doch nur auf der Serverseite, oder? (Die Clientseite ist mir aktuell nicht wichtig, da es sich um Flash-Clients handelt).
Ich gehe davon aus, daß jede Verbindung ihren eigenen Buffer hat. Ist das richtig so?

alex0801 hat gesagt.:
Werde versuchen das mal zu messen...
Wie geht man da am besten vor? Viele Verbindung von einem ClientPC bringen warscheinlich nicht das gewünschte Ergebnis, oder?


viele Grüße,
Käse
 
T

tuxedo

Gast
>> D.h. wenn ich zig Clients auf einem Server habe und eine Nachricht an alle verschicken will, bin ich gezwungen Client für Client abzuarbeiten? Kannst du mir evtl. einen Link geben, wo darauf hingewiesen wird? (Ansonsten suche ich auch heute abend allein danach, hab nur im mom. keine Zeit)

Korrekt. So wurde es in mehreren Quellen geschrieben. Aber es steht auch dabei, dass das Geschwindigkeitstechnisch absolut kein Problem sei.

"key"'s über mehrere Threads zu verteilen ist ein gewaltiger Aufwand was die synchronisation angeht (kann da ein Lied davon singen, und ich habe lediglich einen Dispatch-Thread der sich auch ums senden kümmert und mehrere Empfangsthreads die sich ums empfangen kümmern (scheint mir die beste Lösung zu sein)).

>> Ich gehe davon aus, daß jede Verbindung ihren eigenen Buffer hat. Ist das richtig so?

Korrekt. Es wird zwar gemiltiplext, aber dennoch hat jeder am Server registrierte Client eine eigene Socketverbindung mit einem eigenen Puffer.

>> Wie geht man da am besten vor? Viele Verbindung von einem ClientPC bringen warscheinlich nicht das gewünschte Ergebnis, oder?

Ich hab bis jetzt so getestet: Server läuft ganz normal. Dazu hab ich dann 3-5 Clients gestartet, welche jeweils mit 1000 Threads den Server "stressen". Konkret geht's bei mir um eine Art RMI Ersatz, realisiert mit Java NIO und nur einer Socketverbindung pro Client für den Hin und Rückweg (RMI macht da mehr oder weniger was es will). Dass ich nur 3-5 Clients habe, macht bei mir nix aus, da ich auch nur einen Dispatch-Thread habe der die eintreffenden Pakete in die einzelnen Bearbeitungsthreads verteilt.

Ergebnis bis jetzt: Mein Server schafft 10.000 Remote-Methodenaufrufe von den Clients. PRO SEKUNDE! Getestet hab ich für den extrem-Test via localhost um Netzwerkprobleme auszuschließen. Und bei 10.000 Methodenaufrufen pro Sekunde geht da schon einiges durch die Leitung. AFAIK hat eine Java Socketverbindung per Default 8k Puffergröße. Und bei meinem Extrem-Test hab ich nur vereinzelt 1-3mal pro Minute ein solches "Sendepuffer ist voll" Problem.

Von daher würde ich sagen: Auf einem normalen Serversystem, mit "normaler" Auslastung gibts da keine Geschwindigkeitsprobleme was das leeren des Puffers betrifft.

Nen Link hab ich gerade nicht parat. Müsste ich erst wieder raussuchen (sollte mal wieder meine Bookmarks aufräumen).

- Alex
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Frage zum Keystore Netzwerkprogrammierung 21
E Socket Frage Netzwerkprogrammierung 6
T Frage bzgl. Socket-API Netzwerkprogrammierung 1
C Jetty 9 Non Blocking Handler Frage... Netzwerkprogrammierung 1
O log4j Appender Frage Netzwerkprogrammierung 6
T Frage zu Client-Server Applikation Netzwerkprogrammierung 2
M Theoretische Frage zu Server - Client Netzwerkprogrammierung 2
C Frage zu Threads & Server Netzwerkprogrammierung 4
P Eine etwas andere Frage: Sicherheit Netzwerkprogrammierung 5
M allgemeine Frage über Server-Client-Kommunikation Netzwerkprogrammierung 5
M allgemeine Frage zu einem Web Service Client Netzwerkprogrammierung 2
Q Frage zur Socketprogrammierung Netzwerkprogrammierung 12
D HTTP Frage zu Login & Session ID Netzwerkprogrammierung 5
D HTTP nochne frage zu http requests Netzwerkprogrammierung 6
D "Fileserver" Frage + Mit Java zugreifen Netzwerkprogrammierung 9
S Socket-Frage zu einem LAN-Spiel. Netzwerkprogrammierung 3
Helgon Socket Socket IP Frage + Tutorial/Bücher Netzwerkprogrammierung 5
C Webservice Frage Netzwerkprogrammierung 2
M RMI Code Frage: Netzwerkprogrammierung 4
C Frage zur Klasse DatagramPacket Netzwerkprogrammierung 2
S Einfache Server Frage Netzwerkprogrammierung 5
xDarkSunx Kleine Frage authentifizierung Netzwerkprogrammierung 13
G Frage zu Servlets und deren Objekte + Bilder in Servlets anzeigen? Netzwerkprogrammierung 11
H Input-/OutputStream Frage Netzwerkprogrammierung 6
N Frage zu JNDI Netzwerkprogrammierung 2
B Frage zu einer Lösung (RMI) Netzwerkprogrammierung 2
X FAQ Frage - Netzwerkgrundlagen - ServerSocket und Socket Netzwerkprogrammierung 4
G Netzwerk IP Frage Netzwerkprogrammierung 4
S NanoHTTPD Server frage Netzwerkprogrammierung 5
E einfache Frage: wie Fehler untersuchen mit Tomcat Netzwerkprogrammierung 5
E Einfache Frage zu servlets und netbeans 6.5 Netzwerkprogrammierung 41
N Frage/Problem mit RMI Netzwerkprogrammierung 3
Kr0e Frage zu SO_TIMEOUT Netzwerkprogrammierung 3
K SCP und die Frage: Wie geh ich damit um? Netzwerkprogrammierung 7
G Frage zu Serversocket-Beispiel aus der FAQ Netzwerkprogrammierung 17
A Frage zur Verschlüsselung mit CipherInputStream Netzwerkprogrammierung 7
H Frage zu RMI Netzwerkprogrammierung 4
5 Grundlegende Design-Frage zu Webservices Netzwerkprogrammierung 16
C Frage zur ipcam WVC54GC von linksys ? Netzwerkprogrammierung 1
ven000m Mittlere Wartezeit Frage Netzwerkprogrammierung 5
T Frage bei Irc Verbindung Netzwerkprogrammierung 10
ven000m Frage aus einer mündl. Prüfung - wer kennt die Antwort? Netzwerkprogrammierung 6
S Serveranfrage - allgemeine Frage Netzwerkprogrammierung 2
ven000m Thread Frage Netzwerkprogrammierung 11
D Frage: Buffered Reader --> Wie komm ich an die Daten (Byt Netzwerkprogrammierung 3
H Frage zur Performance Netzwerkprogrammierung 10
flashfactor Frage zu HTML-Response Netzwerkprogrammierung 4
S GEHT DAS? - Nur eine Frage! (Printer Port direkt ansteuern?) Netzwerkprogrammierung 4
K Frage zu Net Send Netzwerkprogrammierung 7
G Frage zu JNDI / RMI Netzwerkprogrammierung 4
A ServerSocket prinzipielle Frage Netzwerkprogrammierung 5
M generelle Frage zum Versenden Netzwerkprogrammierung 4
L Frage nach Socket Netzwerkprogrammierung 4
E frage zu streams Netzwerkprogrammierung 2
Luma Verschiedene Frage zu nem Netzwerkprog Netzwerkprogrammierung 6
G einfache Frage zu ServerSocket ... Netzwerkprogrammierung 5
R Seltsames Verhalten bei GET Request Netzwerkprogrammierung 7
S Seltsames Verhalten beim Empfangen von Daten über DataInputStream Netzwerkprogrammierung 12
B SocketChannel ByteBuffer Bilder verschicken Netzwerkprogrammierung 17
lumo SocketChannel + Write Netzwerkprogrammierung 11
A FileChannel+SocketChannel:Datei wird nur teilweise übertrage Netzwerkprogrammierung 4
A Was kann SocketChannel was Socket nicht kann? Netzwerkprogrammierung 11
P SocketChannel & Socket & JDom & Encoding Netzwerkprogrammierung 4

Ähnliche Java Themen

Neue Themen


Oben