• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

[JAVA] Best Practice für Sockets bei Netzwerkproblemen?

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
Grüß euch,

einmal als Ausgangsbasis:

ich habe einen Multiuser-Chat-Server. Dieser Server hat pro User 2 Threads (Lesen/Schreiben), sprich bei einem Verbindungsabbruch (bsp. durch Hard-Reset wg. Terminierung eines Clients durch die IDE) wirft meine Incoming-Verbindung eine Exception und ich entferne daraufhin die Threads sowie die Verbindung aus meinem User-Pool.

Was ist jetzt die Best Practice für eine Socket Verbindung wenn es zu einem Problem kommt ala Netzwerk ist kurzfristig nicht verfügbar. Die Socket-Verbindung kann ich ja eigentlich weiterhin verwenden sobald das Netzwerk wieder funktioniert, oder? Soll ich dann einfach hergehen und eine gewisse Zeitspanne warten, bevor ich dann noch einmal von dem Socket probiere zu lesen und erst nach bsp. 3-5 Versuchen die Verbindung abbrechen? Oder ist ein direkter Kill der Verbindung deutlich besser?

LG
 

accC

gesperrt

Registriert
14 Juli 2013
Beiträge
5.250
Was würde denn dagegen sprechen die Verbindung zu killen und eine neue aufzubauen, sobald der Client sich wieder meldet?
 

Mr_J

Neu angemeldet

Registriert
14 Juli 2013
Beiträge
991
[...]ala Netzwerk ist kurzfristig nicht verfügbar[...]

Kann man so etwas nicht über den Timeout regeln? Grundsätzlich würde ich allerdings die Verbindung relativ fix killen und dann warten dass der Client sich neu verbindet. Solange dies nicht besonders aufwändig oder andersweitig problematisch ist würde ich keine halbtoten bis ganz toten Verbindungen versuchen aufrecht zu erhalten außer es gibt einen wirklich plausiblen Grund dafür.

MfG
Mr. J
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #4
Bzgl. Timeout: Da bin ich mir nicht ganz sicher wie bzw. ob ich einen Timeout am Socket einstellen kann. Notfalls hätte ich das nämlich wirklich über einen "Pfusch" via Try/Catch gemacht und bei genügend verstrichener Zeit die Verbindung gekillt, das wäre wohl auf das Gleiche wie ein Timeout gekommen.

Einen plausiblen Grund gibt es dafür nicht, ich kenne es halt aus Spielen wo nicht sofort, wenn die Verbindung weg ist, das Spiel unterbrochen wird sondern erst nach einer gewissen Zeit etwas geschieht (als Beispiel sei hier World of Warcraft genannt). Deshalb habe ich mich gefragt ob man die Socket-Verbindung einfach ohne Weiteres weiterverwenden kann oder man es sofort killen sollte. Wenn ihr aber der Meinung seid das man die Verbindung einfach killen und sobald alles wieder rennt einfach neu aufbauen soll werde ich das drinnen belassen.
 

Mr_J

Neu angemeldet

Registriert
14 Juli 2013
Beiträge
991
Der Timeout sollte mit Socketname.setSoTimeout einstellbar sein, wenn die Zeit rum ist ohne das etwas passiert ist sollte eine Exception geworfen werden die man dann entsprechend fangen und den Socket schließen kann. Zur Frage ob man das sofort machen soll oder nicht würde ich halt danach gehen ob es besondere Vorteile oder Nachteile gibt. Ich weis nicht wie aufwändig es bzgl. Rechenzeit ist einen neuen Socket zu öffnen anstatt den Alten lieber etwas weiter offen zu lassen. Wenn die Zahl der verfügbaren Verbindungen zum Server allerdings ausreichend groß ist kann man sich durchaus erlauben etwas zu warten. Das könnte letzten Endes auf der Clientseite halt etwas komfortabler sein, da der Client dann nicht neu connecten muss (stelle ich mir zumindest grad so vor).

MfG
Mr. J
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #6
Ich hab mir gerade die Javadoc zu setSoTimeout durchgelesen. Prinzipiell ist es recht interessant, nur das stößt sich an meinem momentanen Design (Client schickt nichts für eine längere Zeit an den Server, ist aber nach wie vor aktiv). Für so etwas wie einen Heartbeat der in zyklischen Abständen erfolgt ist die Methode sicherlich recht interessant da man dann auch darauf reagieren kann wenn die Socket-Verbindung weiterhin offen ist aber sich bsp. der Client in einen Deadlock verfangen hat.

Bzgl. Client: Da könnte ich ein Autoreconnect einbauen das einfach versucht einen Socket erneut aufzumachen. Wenn der Server nicht verfügbar ist weiß dann wenigstens der User das es da etwas hat und ich muss mich Serverseitig nicht weiter drum kümmern. Das muss ich mir mal in Ruhe genauer anschauen.
 

Mr_J

Neu angemeldet

Registriert
14 Juli 2013
Beiträge
991
Grundsätzlich wäre mal die Frage wie du momentan die Timeouts erkennst. Außer dem Check über den setSoTimeout würde mir nur die harte Tour einfallen, dass beim Schreibversuch eine Exception fliegt und du entsprechend darauf reagierst. An diesem Punkt könnte man natürlich einen Check einbauen, der einfach einen bestimmten Zeitpunkt wartet und nochmal einen Versuch startet bevor der Socket geschlossen wird. Wahlweise könnte man das ganze auch mit mehrfachem Check machen so dass man z.B. alle 3 Sekunden prüft und das Ganze 10mal versucht und erst bei einem Mißerfolg den Socket zu macht.

MfG
Mr. J
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
  • Thread Starter Thread Starter
  • #8
Thread für Lesen der Message von Socket
[src=java]
public void run() {
this.setThreadName();
while(true) {
String message = "";
try {
message = this.bufferedReader.readLine();
} catch (IOException e) {
this.socketConnection.removeCommunication();
break;
}
if (!message.isEmpty()) {
this.controller.addToMessageQueue(message);
}
}
}
[/src]

Thread zum Schreiben der Messages (Ja mir ist grad bewusst geworden das ich hier nicht bzgl. IOExceptions beim Schreiben in den Socket überprüf, das muss ich noch absichern)
[src=java]
public void run() {
this.setThreadName();
while(true) {
List<String> queueCopy;
synchronized(this.messageQueue) {
if (this.messageQueue.isEmpty()) {
try {
System.out.println(String.format("%s going to sleep", this.threadName));
this.messageQueue.wait();
System.out.println(String.format("%s awakening", this.threadName));
} catch (InterruptedException e) {
// TODO OutgoingSocketCommunication Logmessage für Thread Beenden hinzufügen
System.out.println(String.format("%s was interrupted, going to die...", this.threadName));
break;
}
}
queueCopy = new ArrayList<String>(this.messageQueue);
}
for (String message : queueCopy) {
this.printWriter.println(message);
}
synchronized (this.messageQueue) {
this.messageQueue.removeAll(queueCopy);
}
}
}
[/src]

Sobald mein Lese-Thread eine IOException erhält ruft dieser in meiner SocketConnection eine Methode auf, die den Schreib-Thread interrupted für den Ausstieg aus der Endlosschleife. Jetzt wäre eine Variante, das ich den Write-Thread einfach schlafen schicke und der Input-Thread versucht, 3x alle 10 Sekunden nochmal vom Server zu lesen. Wenn er es schafft kann der Output-Thread weiterarbeiten (sprich wird aufgeweckt), ansonsten interrupte ich den Write-Thread und beende ihn damit. Die andere Variante wäre das ich halt sofort kill und den User dafür verantwortlich mache das er erneut versucht eine Verbindung aufzubauen.
 

Mr_J

Neu angemeldet

Registriert
14 Juli 2013
Beiträge
991
Ich glaube ich würde dann die Variante mit mehrfachen Probieren nehmen, sollte allerdings sowohl für Read als auch Write gemacht werden und was ich wesentlich wichtiger finde ist, dass der Server einen solchen Check hat damit dieser nicht irgendwann mit toten Connections überlastet ist.

MfG
Mr. J
 
Oben