1。NIOライブラリの紹介
1。バッファバッファー
バッファーとは、書き込まれて読み出すデータを含むオブジェクトです。
NIOでは、すべてのデータがバッファで処理されます。データを読み取るときは、チャネルからバッファーに直接読み取られ、データを書き込むときは、バッファーからチャネルにも書き込まれます。
バッファーは基本的にアレイであり、通常はバイト配列(ByteBuffer)、または他のタイプの配列です。さらに、バッファーは、データへの構造化されたアクセスや読み取りおよび書き込みの場所の維持などの情報も提供します。
バッファクラスの継承関係を下の図に示します。
2。チャネル
チャネルは、ネットワークデータがチャネルを介して読み取りおよび書き込まれるチャネルです。チャネルとストリームの違いは、チャネルが双方向であること(チャネルを使用して後者を同時に読み取り、書き込むことができる)であり、ストリームは一方向にのみ移動することです。
チャネルは、ネットワークの読み取りと書き込みのためのselectablechannel(Serversocketchannelとsocketchannelはサブクラス)とファイル操作用のFileChannelの2つのカテゴリにほぼ分割できます。
次の例は、FileChannelを使用してファイルを使用してファイルにデータを書き込み、ファイルからデータを読み取り、ファイルデータを別のファイルにコピーするファイルを示しています。
public class niotest {public static void main(string [] args)throws ioexception {copyfile(); } //ファイルをコピーprivate static void copyfile(){fileinputStream in = null; fileoutputStream out = null; try {in = new FileInputStream( "src/main/java/data/in-data.txt"); out = new fileoutputStream( "src/main/java/data/out-data.txt"); filechannel inchannel = in.getChannel(); filechannel outchannel = out.getChannel(); bytebuffer buffer = bytebuffer.allocate(1024); int bytesread = inchannel.read(buffer); while(bytesread!= -1){buffer.flip(); outchannel.write(バッファー); buffer.clear(); bytesread = inchannel.read(buffer); }} catch(filenotfoundexception e){// todo auto-enerated catch block e.printstacktrace(); } catch(ioException e){// todo auto-fenated catch block e.printstacktrace(); }} // write file private static void writefilenio(){try {randomaccessfile fout = new RandomAccessFile( "SRC/MAIN/JAVA/DATA/NIO-DATA.TXT"、 "RW"); filechannel fc = fout.getChannel(); bytebuffer buffer = bytebuffer.allocate(1024); buffer.put( "hi123" .getBytes()); buffer.flip(); {fc.write(buffer); } catch(ioException e){// todo auto-fenated catch block e.printstacktrace(); }} catch(filenotfoundexception e){// todo auto-enerated catch block e.printstacktrace(); }} // read file private static void readfilenio(){fileinputStream fileinputStream; try {fileInputStream = new FileInputStream( "SRC/MAIN/JAVA/DATA/NIO-DATA.TXT"); FileChannel fileChannel = fileInputStream.getChannel(); // fileInputStream bytebuffer = bytebuffer.allocate(1024); //バッファーint bytesread = filechannel.read(bytebuffer); */ bytebuffer.flip(); // hasRemaining():現在の位置と制限の間に要素があるかどうかを通知します。 } /**バッファをクリア*位置= 0; * limit =容量; */ bytebuffer.clear(); bytesread = filechannel.read(bytebuffer); }} catch(filenotfoundexception e){// todo auto-enerated catch block e.printstacktrace(); } catch(ioException e){// todo auto-fenated catch block e.printstacktrace(); }}}3。マルチプレクサセレクター
マルチプレクサは、準備が整ったタスクを選択する機能を提供します。セレクターは、登録されているチャネルを常に投票します。チャネルが読み取りまたは書き込みイベントを送信する場合、チャンネルは準備が整った状態になり、セレクターによって投票されます。次に、selectionキーを通じて一連の準備チャネルを取得して、後続のI/O操作を実行できます。
マルチプレクサセレクターは、複数のチャネルを同時に投票できます。 JDKは従来の選択実装ではなくePollを使用するため、最大接続ハンドル1024/2048の制限はありません。つまり、セレクターの世論調査に責任を負うために必要なスレッドのみが1つのスレッドのみが必要であり、数千のクライアントにアクセスできます。モデルを以下の図に示します。
単一のスレッドでセレクターを処理します。セレクターを使用するには、チャネルをセレクターに登録してから、select()メソッドを呼び出す必要があります。この方法は、登録されたチャネルのイベントの準備ができるまでブロックされます。このメソッドが戻ったら、スレッドは新しい接続、データ受信など、これらのイベントを処理できます。
注記:
1.どのモデルを選択しましたか?
Selectは、待機イベントが発生したときに処理をトリガーするイベントトリガーメカニズムであり、主にサーバーのLinux実装によってクライアントの処理に使用されます。
デバイスがイベントをトリガーするか、指定された待機時間を超えるまで、イベント(読み取り可能、書き込み可能な、優先度エラー出力など)があるかどうかにかかわらず、非ブロッキングをサポートする非ブロッキングIOデバイスのセットを同時に検出できます。つまり、彼らの責任はIOを行うことではなく、発信者が現在準備が整ったデバイスを見つけるのを助けることです。
2。epollモデルとは何ですか?
ePollのデザインのアイデアは、Select/Pollの単一操作を1 epoll_create + Multiple epoll_ctrl + 1回の待機に分割することです。さらに、カーネルは、ePoll操作にファイルシステム「EventPollfs」を追加しました。監視する各ファイル記述子には、対応するEventPollfsファイルシステムのイノードノードがあり、主な情報はEventPoll構造に保存されます。監視されたファイルの重要な情報は、象徴構造に保存されます。したがって、彼らは一つの関係です。
2。NIOサーバー側の開発
関数の説明:サーバー側をオンにして、各アクセスクライアントにHello Stringを送信します。
サーバー側の開発にNIOを使用するためのいくつかの主な手順があります。
1. Serversocketchannelを作成し、非ブロッキングモードに設定します
serversocketchannel = serversocketchannel.open(); serversocketchannel.configureblocking(false);
2。バックログサイズなどのリスニングと構成TCPパラメーターをバインドして構成します
serversocketchannel.socket()。bind(new inetsocketAddress(8080));
3.マルチプレクサセレクターを投票するための独立したI/Oスレッドを作成する
4.セレクターを作成し、以前に作成したServersocketchannelをセレクターに登録し、selectionkey.acceptを聞く
selector = selector.open(); serversocketchannel.register(selector、selectionkey.op_accept);
5。I/Oスレッドを起動し、selector.select()メソッドをループ本体で実行し、準備完了チャネルにポーリングします
while(true){try {// select()登録したイベントで少なくとも1つのチャネルが準備が整うまでブロックします//ここでブロックされる// select(long timeout)はselect()と同じですが、タイムアウトミリ秒(パラメーター)をブロックすることを除きます。 selector.select(); } catch(ioException e){// todo auto-fenated catch block e.printstacktrace();壊す; }}6.準備が整った状態でチャネルを投票する場合、判断する必要があります。 OP_ACCEPT状態の場合、それは新しいクライアントアクセスであることを意味します。次に、新しいクライアントを受け入れるためにServersocketchannel.accept()メソッドを呼び出します。
// Ready SelectionKeyを返してから、繰り返し<selectionKey> readkeys = selector.selectedKeys()を実行して実行します。 for(iterator <selectionKey> it = readkeys.iterator(); it.hasnext();){selectionkey key = it.next(); it.remove(); try {if(key.isaceptable()){serversocketchannel server =(serversocketchannel)key.channel(); socketchannel client = server.accept(); client.configureblocking(false); client.register(selector、selectionkey.op_write); } else if(key.iswritable()){socketchannel client =(socketchannel)key.channel(); bytebuffer buffer = bytebuffer.allocate(20);文字列str = "hello"; buffer = bytebuffer.wrap(str.getBytes()); client.write(buffer); key.cancel(); }} catch(ioexception e){e.printstacktrace(); key.cancel(); try {key.channel()。close(); } catch(ioException e1){// todo auto-feenated catch block e1.printstacktrace(); }}}7.新しくアクセスしたクライアントリンクSocketchannelを非ブロッキングモードに設定し、他のTCPパラメーターを構成します。
if(key.isaceptable()){serversocketchannel server =(serversocketchannel)key.channel(); socketchannel client = server.accept(); client.configureblocking(false); ...}8。Socketchannelをセレクターに登録し、op_writeを聴きます
client.register(selector、selectionkey.op_write);
9.ポーリングされたチャネルがOP_WRITEである場合、それはデータがソックチャネルに書き込まれることを意味します。その後、ByteBufferオブジェクトが構築され、データパケットが記述されます。
else if(key.iswritable()){socketchannel client =(socketchannel)key.channel(); bytebuffer buffer = bytebuffer.allocate(20);文字列str = "hello"; buffer = bytebuffer.wrap(str.getBytes()); client.write(buffer); key.cancel(); }完全なコードは次のとおりです。
java.io.ioexception; Import java.net.inetsocketAddress; Import java.nio.nio.nio.channels.selectionKey; Import Java.nio.channels.selector; Import java.nio.channels.selector; Import Java.nio.nio.channels.serversockannel; java.nio.channels.socketchannel; Import java.util.iterator; import java.util.set; public class serversocketchanneldemo {public static void main(string [] args){serversocketchannel serversocketchannel; selversector selector = null; serversocketchannel.open(); serversocketchannel.configureblocking(false); serversocketchannel.socket()。bind(new inetsocketAddressress(8080)); selector = selector.open(); serversockenchannel.register(selector、selectionkey.op_iccept);} catch(ioexception e) blocke.printstacktrace();} while(true){try {// select()登録されたイベントで少なくとも1つのチャネルが準備ができているまでブロックします//すべての時間をブロックします。 selector.select();} catch(ioexception e){// todo auto-feenated catch blocke.printstacktrace();} // redyed selectionkeyを返し、set <selectionkey> readkeys = selector.selecturedKeys(); key = it.next(); it.remove(); try {if(key.isaceptable()){serversocketchannel server =(serversocketchannel)key.channel(); socketchannel client = server.accept(); client.configureblocking(false); client.op_write、selectoreckey.op_write); {socketchannel client =(socketchannel)key.channel(); bytebuffer buffer = bytebuffer.allocate(20); string str = "hello"; buffer = bytebuffer.wrap(); client.write(buffer); key.cancel(); {e.printstacktrace(); key.cancel(); try {key.channel()。close();} catch(ioexception e1){// todo auto-feenated catch blocke1.printstacktrace();}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}Telnet LocalHost 8080を使用して、複数のクライアントをシミュレートします。
プログラムの実行結果は次のとおりです。
要約します
上記は、この記事のJava Nioサーバー側の開発の詳細な説明です。誰にとっても役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!