この記事では主に Java でノンブロッキング I/O を使用する方法について説明します。また、ノンブロッキング I/O を使用してクライアントを実装する方法も示します。必要な場合はそれを参照できます。
ほとんどの知識と例は、O'REILLY の『Java Network Programming, Fourth Edition, by Elliotte Rusty Harold (O'REILLY)』から得ています。
ノンブロッキング I/O の概要
ノンブロッキング I/O (NIO) は、高い同時実行性を処理する手段です。同時実行性が高い場合、スレッドの作成とリサイクル、およびスレッド間の切り替えのオーバーヘッドが無視できなくなります。このとき、ノンブロッキング I/O テクノロジを使用できます。このテクノロジーの中心となるアイデアは、準備された接続を一度に選択し、その接続で管理できる限り多くのデータをできるだけ早く埋めてから、次の準備された接続に移動することです。
ノンブロッキングI/Oを使用して実装されたクライアント
通常、クライアントは多数の同時接続を処理する必要はありません。実際、ノンブロッキング I/O は主にサーバー向けに設計されていますが、クライアントでも使用できます。クライアントの設計はサーバーの設計よりも簡単であるため、以下の簡単なデモではクライアントを使用します。
まずchannelとバッファを紹介します。 SocketChannel クラスは、ノンブロッキング I/O で接続を作成するために使用されます。 SocketChannel オブジェクトを取得するには、SocketAddress オブジェクト (通常はそのサブクラス InetSocketAddress) をその静的ファクトリ メソッド open() に渡す必要があります。以下に例を示します。
SocketAddress address = new InetSocketAddress("127.0.0.1", 19); SocketChannel client = SocketChannel.open(address);
open() メソッドはブロックしているため、これ以降のコードは接続が確立されるまで実行されません。接続を確立できない場合は、IOException がスローされます。
接続が確立されたら、入力と出力を取得する必要があります。従来の getInputStream() や getOutputStream() とは異なり、チャネルを使用すると、チャネル自体に直接書き込むことができます。バイト配列に書き込む代わりに、ByteBuffer オブジェクトが書き込まれます。 ByteBuffer オブジェクトは ByteBuffer.allocate(int Capacity) によって取得されます。Capacity はバイト単位のバッファ サイズです。ソケットから読み取られたデータがこのバッファに格納されます。 read() メソッドは、正常に読み取られてバッファに保存されたバイト数を返します。デフォルトでは、少なくとも 1 バイトを読み取るか、データの終わりを示す -1 を返し、使用可能なバイトがない場合はブロックします。これは、InputStream とほぼ同じように動作します。ただし、ノンブロッキング モードに設定されている場合、使用可能なバイトがない場合はすぐに 0 が返され、ブロックされません。
ここで、バッファー内に既にデータがあり、後でそれを抽出する必要があると仮定します。従来の方法を使用して、最初にデータをバイト配列に書き込み、次にそれを出力ストリームに書き込むことができます。これは完全にチャネルベースのメソッドです。Channels ツール クラスを使用して、出力ストリームをチャネルにカプセル化します。
ByteBuffer buffer = ByteBuffer.allocate(74);
上記のコードは、System.out をチャネルにカプセル化します。この後、出力を行うことができます。 ByteBuffer オブジェクトの各出力の前に、チャネルが最初から読み取りを開始できるように、その flip() メソッドを呼び出す必要があります。読み取りと書き込みの後、clear() メソッドを呼び出してバッファのステータスをリセットする必要があります。データ出力のコードは次のとおりです:
WritableByteChannel out = Channels.newChannel(System.out);例 1: ノンブロッキング I/O を使用して実装された CharGenerator (文字ジェネレーター) クライアント
サーバー コード:
buffer.flip(); out.write(buffer); buffer.clear();
クライアント コード:
public static void createCharGeneratorServer(){ try(ServerSocket server = new ServerSocket(19)){ while(true){ try(Socket connection = server.accept()){ OutputStream out = connection.getOutputStream(); int firstPrintableCharacter = 33; int numberOfPrintableCharacter = 94; int numberOfCharactersPerLine = 72; int start = firstPrintableCharacter; while(true){ for(int i = start ; i < start + numberOfCharactersPerLine ; i++){ out.write (firstPrintableCharacter + (i - firstPrintableCharacter) % numberOfPrintableCharacter); } out.write('\r'); out.write('\n'); start = firstPrintableCharacter + (start + 1 - firstPrintableCharacter) % numberOfPrintableCharacter; } }catch (IOException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } }ノンブロッキングモードを有効にする
上記のプログラムは、入出力ストリームを使用する従来の方法とあまり変わりません。ただし、ServerSocket の configureBlocking(false) メソッドを呼び出して非ブロッキング モードに設定することができます。このモードでは、利用可能なデータがない場合、read() メソッドはすぐに戻り、クライアントは他のことを行うことができます。ただし、データを読み取れない場合、read() メソッドは 0 を返すため、データを読み取るループにいくつかの変更を加える必要があります。
以上がJava でノンブロッキング I/O を使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。