Socket vs. SocketChannel

Lesezeit: 7 Minuten

Benutzer-Avatar
Ramzi Khahil

Ich versuche zu verstehen SocketChannelsund NIE Im Algemeinen. Ich weiß, wie man mit regulären Sockets arbeitet und wie man einen einfachen Thread-pro-Client-Server erstellt (unter Verwendung der regulären blockierenden Sockets).

Also meine Fragen:

  • Was ist ein SocketChannel?
  • Was ist das Extra, das ich bekomme, wenn ich mit einem SocketChannel anstelle eines Sockets arbeite?
  • Welche Beziehung besteht zwischen einem Kanal und einem Puffer?
  • Was ist ein Selektor?
  • Der erste Satz im Dokumentation ist A selectable channel for stream-oriented connecting sockets.. Was bedeutet das?

Ich habe das auch gelesen diese Dokumentationaber irgendwie bekomme ich es nicht hin…

  • Ich muss mich für die anderen entschuldigen, die Ihre Frage wegen des Hintergrunds und nicht wegen des Inhalts abgelehnt haben. Als Kommilitonin im Aufbaustudium verstehe ich es vollkommen, wenn Sie gezwungen sind, einen Kurs zu betreuen, der nicht genau in Ihrem Forschungsgebiet liegt, insbesondere wenn Ihre Finanzierung davon abhängt. Ich finde es auch gut, dass Sie hierher gekommen sind, um sich Klarheit zu verschaffen.

    – Andreas Mao

    9. Januar 2013 um 0:25 Uhr

Benutzer-Avatar
Andreas Mao

EIN Socket ist ein blockierendes Ein-/Ausgabegerät. Es macht die Thread Das heißt, es wird zum Blockieren von Lesevorgängen und möglicherweise auch zum Blockieren von Schreibvorgängen verwendet, wenn der zugrunde liegende Puffer voll ist. Daher müssen Sie eine Reihe verschiedener Threads erstellen, wenn Ihr Server eine Reihe von offenen Threads hat Sockets.

EIN SocketChannel ist eine nicht blockierende Methode zum Lesen von Sockets, sodass ein Thread gleichzeitig mit einer Reihe offener Verbindungen kommunizieren kann. Dies funktioniert durch Hinzufügen einer Reihe von SocketChannels zu a Selectordann Schleife auf dem Selektor select() -Methode, die Sie benachrichtigen kann, wenn Sockets akzeptiert, Daten empfangen oder geschlossen wurden. Auf diese Weise können Sie mit mehreren Clients in einem Thread kommunizieren und haben nicht den Overhead mehrerer Threads und der Synchronisierung.

Buffers sind eine weitere Funktion von NIO, die es Ihnen ermöglicht, auf die zugrunde liegenden Daten von Lese- und Schreibvorgängen zuzugreifen, um den Aufwand für das Kopieren von Daten in neue Arrays zu vermeiden.

  • Vielen Dank. Aber ich habe noch einen fehlenden Punkt. Gibt es einen Vorteil bei der Verwendung eines Kanals ohne Selektor? oder kommen sie zusammen?

    – Ramzi Khahil

    9. Januar 2013 um 10:13 Uhr

  • Sie können einen Kanal nicht ohne einen Selektor verwenden, weil der Selektor Ihnen beispielsweise mitteilt, wann ein Kanal zum Lesen bereit ist. Ich kann mir keinen Grund vorstellen, warum Sie Kanäle selbst verwenden möchten, da Sie im Grunde die Funktionalität des Selektors neu implementieren würden.

    – Andreas Mao

    9. Januar 2013 um 18:21 Uhr

  • Entschuldigung, aber auf welche Weise blockiert SocketChannel nicht? Selector.select() ist ein Blockierung Betrieb. Sie sagten, dass select() benachrichtigt, aber in Wirklichkeit einfach blockiert. Dies kann nicht als Benachrichtigung bezeichnet werden, da es keine Rückrufe verwendet.

    – ZhekaKozlov

    4. Juni 2014 um 2:47 Uhr

  • Terminologie ist nur dann verwirrend, wenn sie missbraucht wird. Das „Non-Blocking“ in „NIO“ bezieht sich auf die „IO“, also die I/O-Operationen. Der Thread ist nicht “verschwendet”, weil er nichts zu tun hat außer E/A. Und nicht blockierende E/A ist nicht dasselbe wie asynchrone E/A: Das ist ein ganz anderes Thema.

    – arayq2

    6. Juni 2014 um 16:14 Uhr


  • @AndrewMao Sie können tatsächlich einen Kanal ohne Selektor verwenden, auch im nicht blockierenden Modus, was nicht die Standardeinstellung ist, obwohl dies nicht empfohlen wird. Das „N“ in „NIO“ steht für „Neu“.

    – Benutzer207421

    7. April 2017 um 10:15 Uhr


Benutzer-Avatar
arayq2

Inzwischen NIO ist so alt, dass sich nur wenige daran erinnern, wie Java vor 1.4 war, was Sie wissen müssen, um das “Warum” von Java zu verstehen NIO.

Kurz gesagt, bis Java 1.3 war alle I/O vom blockierenden Typ. Und schlimmer noch, es gab kein Analogon zu dem select() Systemaufruf für Multiplex-E/A. Infolgedessen hatte ein in Java implementierter Server keine andere Wahl, als eine “Ein-Thread-pro-Verbindung”-Dienststrategie anzuwenden.

Der grundlegende Punkt von NIO, das in Java 1.4 eingeführt wurde, bestand darin, die Funktionalität traditioneller, nicht blockierender Multiplex-I/O im UNIX-Stil in Java verfügbar zu machen. Wenn Sie verstehen, wie man mit programmiert select() oder poll() um die E/A-Bereitschaft für eine Reihe von Dateideskriptoren (normalerweise Sockets) zu erkennen, finden Sie die Dienste, die Sie dafür benötigen, in NIO: du wirst benutzen SocketChannels für nicht blockierende E/A-Endpunkte und Selectors für fdsets oder pollfd-Arrays. Server mit Threadpools oder mit Threads, die jeweils mehr als eine Verbindung handhaben, werden jetzt möglich. Das ist das “Extra”.

EIN Buffer ist die Art von Byte-Array, das Sie für nicht blockierende Socket-E / A benötigen, insbesondere auf der Ausgabe- / Schreibseite. Wenn nur ein Teil eines Puffers sofort geschrieben werden kann, blockiert Ihr Thread beim Blockieren der E / A einfach, bis der gesamte Puffer geschrieben werden kann. Bei nicht blockierender E/A erhält Ihr Thread einen Rückgabewert, der angibt, wie viel geschrieben wurde, und überlässt es Ihnen, den Rest für die nächste Runde zu handhaben. EIN Buffer kümmert sich um solche mechanischen Details, indem es explizit ein Producer/Consumer-Muster zum Füllen und Entleeren implementiert, wobei davon ausgegangen wird, dass Ihre Threads und der JVM-Kernel dies tun nicht synchron sein.

  • SocketChannel blockiert. Wenigstens read() und write() Methoden sind. Der wahre nicht blockierende Kanal ist AsynchronousSocketChanneldas in Java 7 eingeführt wurde.

    – ZhekaKozlov

    4. Juni 2014 um 2:35 Uhr

  • Wirklich? Was ist also mit der Methode configureBlocking(bool) passiert, die seit der Einführung von NIO in Java 1.4 vorhanden war?

    – arayq2

    5. Juni 2014 um 16:08 Uhr

  • Es hört sich so an, als hätten Sie nicht blockierende E / A mit asynchroner E / A verwechselt. Selbst bei asynchroner I/O wird das Blockieren nicht “vollständig eliminiert” – z. B. ist get() auf einem Future<> ein blockierender Aufruf. Das Designproblem ist es nicht ob (Ihre wesentliche Verwirrung) zu blockieren, aber Wenn blockieren.

    – arayq2

    9. Juni 2014 um 2:28 Uhr

  • Rückwärtskompatibilität?? Seufzen. Wie auch immer.

    – arayq2

    9. Juni 2014 um 13:16 Uhr

  • @ZhekaKozlov A SocketChannel im nicht blockierenden Modus ist nicht blockierend. Asynchrone E/A ist ein weiteres Biest, das überhaupt nichts mit dem nicht blockierenden Modus zu tun hat.

    – Benutzer207421

    7. April 2017 um 10:16 Uhr

Benutzer-Avatar
Frank Zhang

Obwohl Sie verwenden SocketChannelsEs ist notwendig, Thread-Pool zu verwenden, um zu verarbeiten channels.

Wenn Sie an das Szenario denken, verwenden Sie nur einen Thread, der für beide Abfragen verantwortlich ist select() und Verarbeitung der SocketChannels ausgewählt aus Selectors, wenn ein Kanal 1 Sekunde für die Verarbeitung benötigt und sich 10 Kanäle in der Warteschlange befinden, bedeutet dies, dass Sie 10 Sekunden vor der nächsten Abfrage warten müssen, was nicht tolerierbar ist. Daher sollte es einen Thread-Pool für die Kanalverarbeitung geben.

In diesem Sinne sehe ich keinen großen Unterschied zum Thread-pro-Client-Socket-Blockierungsmuster. der Hauptunterschied liegt darin NIO Muster, die Aufgabe ist kleiner, es ist eher wie Thread-per-Task, und Aufgaben können gelesen, geschrieben, biz verarbeitet usw. werden. Weitere Details finden Sie unter Netty‘s Umsetzung von NioServerSocketChannelFactoryder einen Boss-Thread verwendet, der eine Verbindung akzeptiert, und Aufgaben zur Verarbeitung an einen Pool von Worker-Threads weiterleitet

Wenn Sie wirklich Lust auf einen Thread haben, sollten Sie unter dem Strich zumindest E / A-Threads gepoolt haben, da E / A-Vorgänge oft um Größenordnungen langsamer sind als Befehlsverarbeitungszyklen. Sie möchten den wertvollen einen Thread nicht durch E/A blockiert werden, und das ist genau das NodeJS Dabei wird eine Thread-Akzeptanzverbindung verwendet, und alle E / A-Vorgänge sind asynchron und werden parallel vom Back-End-E / A-Thread-Pool verarbeitet

ist der Thread-pro-Client im alten Stil tot?
Ich glaube nicht, NIO-Programmierung ist komplex und Multithreading ist nicht von Natur aus böse. Denken Sie daran, dass moderne Betriebssysteme und CPUs beim Multitasking immer besser werden, sodass der Overhead von Multithreading mit der Zeit kleiner wird.

  • Wenn ein Kanal 1 Sekunde für die Verarbeitung benötigt, sollten Sie NIO nicht verwenden.

    – John

    17. November 2015 um 12:12 Uhr

  • @John was würdest du dann verwenden?

    – El Mac

    24. März 2016 um 12:14 Uhr

  • @ElMac offensichtlich mehr als ein einzelner Thread. Das Lesen/Schreiben des Socket-Kanals kann weiterhin als gemultiplexter Einzelthread implementiert werden. Die Verarbeitung der Daten sollte jedoch in einem anderen Thread-Pool erfolgen.

    – bash0r

    12. November 2018 um 16:52 Uhr

1205390cookie-checkSocket vs. SocketChannel

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy