74

私はSocketChannelsNIO全般を理解しようとしています。私は、通常のソケットを操作する方法と、(通常のブロッキングソケットを使用して)単純なクライアントサーバーごとのスレッドを作成する方法を知っています。

だから私の質問:

  • SocketChannelとは何ですか?
  • Socketの代わりにSocketChannelを使用するときに得られる追加の機能は何ですか。
  • チャネルとバッファの関係は何ですか?
  • セレクターとは何ですか?
  • ドキュメントの最初の文はA selectable channel for stream-oriented connecting sockets.です。どういう意味ですか?

私もこのドキュメントを読みましたが、どういうわけか私はそれを取得していません...

4

3 に答える 3

59

ASocketはブロッキング入力/出力デバイスです。これをThread使用して、読み取りをブロックし、基になるバッファがいっぱいの場合は書き込みもブロックする可能性があります。したがって、サーバーに多数のオープンスレッドがある場合は、多数の異なるスレッドを作成する必要がありますSocket

ASocketChannelは、ソケットから読み取るための非ブロッキング方法であるため、1つのスレッドが一度に多数の開いている接続と通信することができます。SocketChannelこれは、 sの束をに追加Selectorし、セレクターのselect()メソッドをループすることで機能します。これにより、ソケットが受け入れられたか、データを受信したか、または閉じられたかを通知できます。これにより、1つのスレッドで複数のクライアントと通信でき、複数のスレッドや同期のオーバーヘッドが発生しなくなります。

Buffer■はNIOのもう1つの機能であり、読み取りと書き込みから基になるデータにアクセスして、データを新しいアレイにコピーするオーバーヘッドを回避できます。

于 2013-01-09T00:31:15.990 に答える
19

NIOでは非常に古いので、1.4より前のJavaがどのようなものであったかを覚えている人はほとんどいません。これは、の「理由」を理解するために知っておく必要のあることですNIO

一言で言えば、Java 1.3までは、すべてのI/Oはブロッキングタイプでした。さらに悪いことに、select()多重化I/Oへのシステムコールの類似物はありませんでした。その結果、Javaで実装されたサーバーは、「接続ごとに1つのスレッド」サービス戦略を採用する以外に選択肢がありませんでした。

Java 1.4で導入されたNIOの基本的なポイントは、従来のUNIXスタイルの多重化ノンブロッキングI/Oの機能をJavaで利用できるようにすることでした。select()一連のファイル記述子(通常はソケット)を使用してI / O準備をプログラムする方法、またはI / O準備を検出する方法を理解している場合はpoll()、それに必要なサービスが次の場所にあります。非ブロッキングI/OエンドポイントにsをNIO使用します。 SocketChannel、およびSelectorsはfdsetsまたはpollfd配列の場合。スレッドプールを備えたサーバー、またはそれぞれが複数の接続を処理するスレッドを備えたサーバーが可能になりました。それが「余分な」ものです。

ABufferは、特に出力/書き込み側で、非ブロッキングソケットI/Oに必要な種類のバイト配列です。バッファの一部のみをすぐに書き込むことができる場合、I / Oをブロックすると、スレッドは全体が書き込まれるまで単純にブロックされます。非ブロッキングI/Oを使用すると、スレッドは書き込まれた量の戻り値を取得し、次のラウンドの残りを処理するのはユーザーに任されます。ABufferは、充填と排出のための生産者/消費者パターンを明示的に実装することにより、このような機械的な詳細を処理します。スレッドとJVMのカーネルは同期し ないことが理解されます。

于 2013-01-09T20:13:51.100 に答える
6

を使用している場合でも、SocketChannels処理にはスレッドプールを使用する必要がありますchannels

選択したもののポーリングselect()と処理の両方を担当するスレッドを1つだけ使用するシナリオを考えると、1つのチャネルの処理に1秒かかり、キューに10のチャネルがある場合、次のポーリングまでに10秒待つ必要があります。耐えられないです。したがって、チャネル処理用のスレッドプールが必要です。SocketChannelsSelectors

この意味で、クライアントごとのスレッドブロッキングソケットパターンに大きな違いは見られません。主な違いはNIOパターンにあり、タスクは小さく、タスクごとのスレッドに似ています。タスクの読み取り、書き込み、ビジネスプロセスなどの詳細については、Nettyの実装をNioServerSocketChannelFactory確認できます。接続を受け入れる1つのBossスレッドを使用しており、処理のためにワーカースレッドのプールにタスクをディスパッチします

I / O操作は命令処理サイクルよりもかなり遅いことが多いため、1つのスレッドが本当に好きな場合は、少なくともI/Oスレッドをプールしている必要があります。貴重な1つのスレッドは必要ありません。 I / Oによってブロックされます。これは、1つのスレッド受け入れ接続を使用してNodeJSが実行していることとまったく同じであり、すべてのI / Oは非同期であり、バックエンドI/Oスレッドプールによって並列処理されます。

古いスタイルのクライアントごとのスレッドは死んでいますか? そうは思いませんが、NIOプログラミングは複雑で、マルチスレッドは当然悪ではありません。最新のオペレーティングシステムとCPUはマルチタスクでますます良くなっているため、マルチスレッドのオーバーヘッドは時間の経過とともに小さくなります。

于 2014-06-03T09:14:01.023 に答える