2016-03-20 5 views
2

Zu Lernzwecken schreibe ich einen Java TCP Server. Dies wird in eine eigene Klasse wie SyteTCPServer verpackt, die ServerSocket verwendet, um Verbindungslogik zu behandeln. Dies ist für ein Schulprojekt, wo gute Code-Praktiken sehr wichtig sind.Java TCP Server Klasse Abstraktion

Der Grund, warum es in eine eigene Klasse versetzt wird, ist, dass es ein spezifisches Protokoll auf Anwendungsebene gibt. Die Klasse ist Teil eines größeren Projekts.

Beim googeln fand ich nur Leute, die alle ServerSocket und die dazugehörige Logik direkt in die Hauptmethode einfügten. Ich bin mir nicht sicher, ob das der richtige Weg ist, wenn es um OOP geht?

Mein SyteTCPServer hat eine einfache Start() und Stop() Verfahren ist es, die Umsetzung verbirgt sich ein ServerSocket der Verwendung von Clients verarbeitet, etc ..

Allerdings bin ich ein bisschen, weil mit viel der Netzwerkfunktionen stapfte, IntelliJ warnt mich vor IOExceptions. Das Akzeptieren eines Clients könnte eine IOException auslösen, also könnte man den Ausgabestrom des besagten Clients bekommen, also könnte writeBytes, .. Sie meinen Punkt bekommen.

Im Zusammenhang mit Abstraktion, wie gehe ich am besten über diese Ausnahmen? Schreibe ich eine throws IOException neben der Methode, die höher-up-Code try...catch die SyteTCPServer.Start?

Sollte auch der gesamte Server stoppen Ausnahmen auftreten, oder "verstecke" ich die Tatsache, dass einer der Clients nicht richtig verbunden? Oder sollte ich ein Ereignis auslösen, wenn ein Client keine Verbindung herstellen konnte? Ich weiß wirklich nicht ..

Ich vermeide es auch, Ausgabe zu schreiben, wenn eine Ausnahme auftritt wie die Pest wegen UI/Core-Code-Trennung.

Ich hoffe, das sind nicht zu viele Fragen in einem.

Hier ist ein Beispiel für die Start-Methode habe ich mit IOException wirft:

public void Start() throws IOException { 
    this.listenSocket = new ServerSocket(this.port); 

    Listen(); 
} 

Antwort

1

Ich denke, es ist wichtig, dass Sie zwischen verschiedenen IOExceptions unterscheiden Sie erhalten könnten. Zum Beispiel, ist es eine Ausnahme beim Erstellen einer neuen Verbindung oder einer, während die Verbindung bereits hergestellt wurde, ist es ein etwas zu erwartender Fehler oder nicht? Der einfachste Weg hierfür ist nur die documentation zu lesen und den Fehler zu behandeln je nachdem, was genau passiert:

Für eine Server-Socket-Konstruktion:

öffentlichen ServerSocket- (int port) throws IOException

  • IOException - wenn beim Öffnen des Sockets ein E/A-Fehler auftritt.
  • SecurityException - wenn ein Sicherheitsmanager vorhanden ist und die checkListen-Methode den Vorgang nicht zulässt.
  • IllegalArgumentException - wenn der Portparameter außerhalb des angegebenen Bereichs gültiger Portwerte liegt, der zwischen 0 und 65535 einschließlich liegt.

Für die Annahme einer Verbindung:

öffentlichen Sockel accept() throws IOException

  • IOException - wenn ein I/O-Fehler tritt auf, wenn für eine Verbindung warten.
  • SecurityException - wenn ein Sicherheitsmanager vorhanden ist und dessen checkAccept-Methode den Vorgang nicht zulässt.
  • SocketTimeoutException - wenn zuvor ein Timeout mit setSoTimeout gesetzt wurde und das Timeout erreicht wurde.
  • IllegalBlockingModeException - falls dieser Buchse einen zugehörigen Kanal hat, ist der Kanal in non-blocking-Modus, und es gibt keine Verbindung bereit

Und so weiter in Kauf genommen werden.

Informationen zum Abfangen der Ausnahme (n): Dies hängt auch davon ab, was Ihr Server in bestimmten Fällen tun soll. Aber fangen Sie im Allgemeinen "erwartete" Fehler ab und behandeln Sie diese dann und wann, aber werfen Sie die nicht beabsichtigten Fehler auf eine höhere Ebene.

Was ich damit meine:

public void foo() throws IOException { 
    try { 
     serverSocket = new ServerSocket(PORT); 
    } catch (IOException e) { 
     // Port is in use -> perhaps retry on another port 
     // If things fail, throw exception anyway 
    } finally { 
     if (!serverSocket.isClosed()) { 
      try { 
       serverSocket.close(); 
      } catch (IOException e) { 
       // This exception is to be taken care of internally, not thrown 
      } 
     } 
    } 
} 

Beachten Sie auch, dass dies für die serverseitige nicht nur anwendbar ist, sondern für die Client-Seite als auch.

Viel Glück beim Schreiben Ihres Servers!

1

Ich fand nur Leute, die alle ServerSocket und die begleitende Logik direkt in die Hauptmethode einfügten. Ich bin mir nicht sicher, ob das der Weg zu ist, wenn es um OOP geht?

Putting all ServerSocket Erstellungscode und seine nachfolgende Logik wie die Annahme, Handhabung und Lese-/Schreib an den Client in einer main() Methode ist direkt definitiv keine gute OOP Praxis.

Mit OOP sollten wir aus einer Perspektive von Objekten denken und wie diese Objekte miteinander interagieren, um die gewünschte Funktionalität zu erfüllen. Und jedes Objekt beinhaltet eine eindeutige Verantwortung.

einen Client Annahme eines IOException werfen könnte, so könnte die Ausgabestrom des Client bekommen, so könnte writebytes, .. Sie meinen Punkt.

Im Zusammenhang mit Abstraktion, wie gehe ich am besten über diese Ausnahmen? Schreibe ich eine throws IOException neben der Methode, der höher-up-Code versuchen ... Fang den SyteTCPServer.Start?

Few Best Practices ich hervorheben kann

  • Vergessen Sie nicht die Ausnahme mit mit allen notwendigen Informationen zu protokollieren, wie es später für die Fehlersuche und andere Verbesserungen unverzichtbares Werkzeug bildet.
  • Nicht die gleiche Ausnahme mit mehreren versuchen/fangen entlang des Flusses.
  • Schlucken Sie die Ausnahmen nicht, nachdem Sie sie abgefangen haben, und wiederholen Sie sie, es sei denn, sie werden nicht wirklich benötigt.
  • Schließlich hängt die Behandlung einer Ausnahme auch davon ab, ob es sich um eine behebbare Ausnahme handelt oder nicht. Wenn die Ausnahme nicht wiederhergestellt werden kann, bereinigen Sie die Ressourcen. Wenn wiederherstellbar, protokollieren Sie die Ausnahme und führen Sie die Schritte zum Wiederherstellen der Ausnahme aus. Und die beste Anleitung hier ist Javadoc für diese API.

Auch sollte der gesamte Server-Stopp muss Ausnahmen auftreten, oder muss ich „verstecken“ die Tatsache, dass einer der Kunden nicht richtig angeschlossen haben? Oder vielleicht, sollte ich ein Ereignis auslösen, wenn ein Client keine Verbindung herstellen konnte?

Wie Sie entlang der Umsetzung des Code gehen, ich bin sicher, dass Sie noch mehr Klassen finden, einer von ihnen sein könnte, jeder Client-Verbindungsanfrage in einem separaten Thread zu handhaben, sagen ClientConnectionHandler Objekt (Thread), so dass andere Clients sind nicht blockiert. Und so würde jede Clientverbindung zu einem unabhängigen Ausführungsstrang werden.

Wenn die Ausnahme für diese Clientverbindung spezifisch ist, ist es bei diesem Entwurf nicht erforderlich, den gesamten Server herunterzufahren. Es genügt, den Client-Thread zu beenden und die Ressourcen zu bereinigen.