この記事では、java に関する関連知識を提供します。主に、NIO コア、BIO と NIO の比較、NIO ターミナル通信を介した単純なサーバー クライアントの実装など、NIO 関連の問題を紹介します。みんなの役に立つでしょう。
java チュートリアル 」
1. Java マインド マップ ##2. I/O モデル
I/O モデルの本質は、どのようなチャネルを使用してデータを送受信するかであり、プログラム通信のパフォーマンスを大きく決定します。
Java は 3 つのネットワーク プログラミング モデルをサポートします: BIO、NIO、AIO- BIO: 同期とブロッキング、サービス実装モードは 1 つの接続と 1 つのスレッドです。つまり、クライアントは1 つの接続 リクエストを行うとき、サーバーは処理のためにスレッドを開始する必要があります。
- NIO: 同期かつノンブロッキングのサーバー実装モードは、複数のリクエスト接続を処理するスレッドです。つまり、クライアントから送信されたリクエストはマルチプレクサに登録され、多重化されます。サーバーは、I/O リクエストの接続をポーリングし、それらを処理します。
- AIO: 非同期ノンブロッキング、AIO は非同期チャネルの概念を導入し、プロアクター モードを採用し、プログラムの作成を簡素化し、有効なリクエストの後にのみスレッドを開始します。その特徴は、オペレーティング システムがまず完了後にサーバーに通知します。
- 3. BIO、NIO、AIO アプリケーション シナリオ
- BIO 方式は、接続数が比較的少なく固定されたアーキテクチャに適しています。この方法は、サーバーのリソース要件が比較的高く、同時実行がアプリケーションに制限されている場合に適しており、JDK1.4 以前はこれしか選択肢がありませんでしたが、プログラムがシンプルで理解しやすいです。
- NIO メソッドは、チャット サーバー、弾幕システム、サーバー間通信など、多数の接続と比較的短い接続 (軽い操作) を行うアーキテクチャに適しています。プログラミングはより複雑になり、JDK1.4 でサポートされ始めます。
- AIO メソッドは、フォト アルバム サーバーなど、多数の接続と比較的長い接続 (重い操作) を伴うアーキテクチャで使用され、同時操作に参加するために OS を完全に呼び出します。プログラミングは比較的複雑で、JDK7 でサポートされ始めています
- 4. BIO プログラミングの簡単なプロセス
- サーバーは ServerSocket を開始します。
- クライアントはソケットを開始します。サーバーと通信するには、デフォルトでサーバーは各クライアントが通信するためのスレッドを確立する必要があります。
- クライアントはリクエストを送信した後、まずスレッド応答があるかどうかをサーバーに問い合わせます、ない場合は待機するか拒否されます;
- 応答がある場合、クライアントはスレッドは実行を続行する前にリクエストが終了するのを待ちます;
- 5 、NIO コア
NIO には 3 つのコア部分があります: セレクター (セレクター)、チャンネル (チャネル)、そしてバッファ(バッファ)。
NIO はバッファ指向、つまりブロック指向のプログラミングです。データはバッファに読み込まれ、後で処理されます。必要に応じてバッファ内でデータを前後に移動できるため、処理プロセスの柔軟性が向上します。 Use It は、ノンブロッキングで拡張性の高いネットワークを提供します。 HTTP2.0 は多重化テクノロジーを使用して、同じ接続で複数のリクエストを同時に処理できるようにしており、同時リクエストの数は HTTP1.1 よりも数桁多くなります。
つまり、NIO は 1 つのスレッドで複数のリクエストを処理できます。
6. BIO と NIO の比較
- BIO はストリーム内のデータを処理しますが、NIO はブロック内のデータを処理します。ブロック I/O はストリーム I より効率的です。 /O. /O ははるかに高い;
- BIO はブロッキング、NIO はノンブロッキング;
- BIO はバイト ストリームに基づいて動作し、文字ストリーム、NIO はチャネルとバッファに基づいて動作します。データは常にチャネルからバッファに読み取られるか、バッファからチャネルに書き込まれます。セレクターは、複数のチャネル イベント (接続要求、データ到着など) を監視するために使用されるため、単一のスレッドで複数のクライアント チャネルを監視できます。
- #7. NIO の 3 つの中心原則の概略図
フローチャートの説明:
- セレクター対応 1 つのスレッド、1 つのスレッドが複数のチャネル (接続) に対応します;
- この図は、セレクター //プログラムに登録されているチャネルが 3 つあることを示しています;
- プログラムがどのチャネルに切り替わるかはイベントによって決定され、イベントは重要な概念です;
- バッファはメモリ ブロックであり、下部には配列があります;
チャネルは双方向であり、Linux などの基礎となるオペレーティング システムのステータスを返すことができます。基礎となるオペレーティング システム チャネルは双方向です。
8. バッファ(バッファ)
バッファは本質的に、データの読み書きができるメモリ ブロックです。コンテナ オブジェクト (配列を含む) として理解できます。このオブジェクトは、使いやすくするためのメソッドのセットを提供します。バッファ オブジェクトには、バッファのステータス変化を追跡および記録できるいくつかの組み込みメカニズムがあります。 Channel はファイルやネットワークからデータを読み取るためのチャネルを提供しますが、読み書きされるデータは Buffer を経由する必要があります。
NIO では、Buffer は最上位の親クラスであり、抽象クラスです。
1. 一般的に使用されるバッファ サブクラスのリスト
ByteBuffer、バイト データをバッファに格納します;
-
ShortBuffer、文字列データをバッファに保存します;
CharBuffer、文字データをバッファに保存します;
IntBuffer、整数データを保存しますバッファに保存;
LongBuffer、長整数データをバッファに保存;
DoubleBuffer、小数をバッファに保存;
FloatBuffer、バッファに小数を格納します;
##2. バッファの 4 つの主要な属性
- #mark: マーク
- position: 位置、読み書きされる次の要素のインデックス。値は、バッファ データが読み書きされるたびに変更されます。次へ 読み取りと書き込みの準備。
- limit: バッファの現在の終了点を示します。制限を超えるバッファでは読み取りおよび書き込み操作を実行できません。また、制限は変更できます。
- capacity: 容量、つまり、収容できるデータの最大量は、バッファの作成時に設定され、変更できません。
#3. 共通バッファ API
## JDK1.4 のときに導入されました
##public Final int Capacity( )//このバッファの容量を返しますpublic Final int Position( )//このバッファの位置を返します- publicfinal Bufferposition( int newPositio )//このバッファの位置を設定します
- publicfinal int limit()//このバッファの制限を返します
- publicfinalBufferlimit(intnewLimit)//このバッファの領域制限を設定します
- publicfinalBuffermark()//このバッファの位置にマークを設定します
- publicfinalBufferreset()//このバッファの位置を前のマークにリセットします Position
- public Final Buffer clear( )//このバッファをクリアします。つまり、各マークを初期状態に戻しますが、データは実際には消去されず、その後の操作で上書きされます
- public Final Buffer lip ( )//このバッファを反転
- public Final Buffer rewind( )//このバッファを巻き戻す
- public Final int Rewind( )//現在位置と制限値の間を返す 要素数
- public Final boolean hasRemaining()//現在位置と制限値の間に要素があるかどうかを通知します
- public abstract boolean isReadOnly();//このバッファが読み取りバッファのみであるかどうかを通知します
- JDK1.6 で導入された API
- #public abstract boolean hasArray();//このバッファにアクセス可能な基になる実装配列があるかどうかを通知します
public abstract Object array();//このバッファの基礎となる実装配列を返します
- public abstract int arrayOffset();//このバッファの基礎となる実装配列の最初のバッファを返します 領域要素のオフセット
- public abstract boolean isDirect();//このバッファがダイレクト バッファかどうかを通知します
- 9. チャネル
1 . 基本的な紹介
チャネルは同時に読み取りと書き込みが可能で、ストリームは読み取りまたは書き込みのみ可能です。
#チャネルはデータを非同期に読み書きできますチャネルはバッファからデータを読み取り、バッファにデータを書き込むことができます- #(2) BIO のストリームたとえば、FileInputStream オブジェクトはデータの読み取りのみが可能ですが、NIO のチャネル (Channel) は双方向であり、読み取りまたは書き込み操作が可能です。 (3) チャネルは NIO のインターフェイスです
- (4) 一般的に使用されるチャネル クラスには、FileChannel、DatagramChannel、ServerSocketChannel、および SocketChannel が含まれます。 ServerSocketChanne は ServerSocket に似ており、SocketChannel は Socket に似ています。 (5) FileChannel はファイルデータの読み書きに使用され、DatagramChannel は UDP データの読み書きに使用され、ServerSocketChannel と SocketChannel は TCP データの読み書きに使用されます。
FileChannel は主にローカル ファイルで IO 操作を実行するために使用されます。一般的なメソッドは次のとおりです:
read 、チャネルからデータを読み取り、バッファに入れます
write、バッファ内のデータをチャネルに書き込みます- transferFrom、からターゲット チャネルから現在のチャネルにデータをコピーします
- transferTo、現在のチャネルからターゲット チャネルにデータをコピーします
3. バッファとチャネルに関する注意と詳細
ByteBuffer は、型付きの put と get、put into データ型をサポートします。 get は、対応するデータ型を使用して取得する必要があります。そうでない場合は、BufferUnderflowException 例外が発生する可能性があります。
通常のバッファを読み取り専用バッファに変換できます。
NIO は、ファイルをメモリ (ヒープ外のメモリ) 内で直接変更できるようにする MappedByteBuffer も提供しており、ファイルの同期方法は NIO によって完了します。
NIO は、複数のバッファ (バッファ配列) を介した読み取りおよび書き込み操作、つまりスキャッタリングとギャザリングもサポートします。
10. セレクター(selector)
1. 基本的な紹介
Java の NIO を使用します。ノンブロッキングIOモード。 1 つのスレッドを使用して複数のクライアント接続を処理でき、セレクターを使用します。
Selector は登録されている複数のチャネルでイベントが発生したかどうかを検出し、イベントが発生した場合はイベントを取得し、それぞれのイベントに応じて処理します。このように、複数のチャネルの管理、つまり複数の接続とリクエストの管理に 1 つのスレッドのみを使用できます。
読み取りと書き込みは、接続/チャネル上に実際の読み取りおよび書き込みイベントがある場合にのみ発生するため、システムのオーバーヘッドが大幅に削減され、接続ごとにスレッドを作成する必要がなくなります。複数のスレッドを維持する必要があります。
複数のスレッド間のコンテキストの切り替えによって発生するオーバーヘッドを回避します。
#2. セレクター関連のメソッド
- ##open();//セレクター オブジェクトを取得します
- select(long timeout);//登録されているすべてのチャネルを監視します。IO 操作が実行できる場合、対応する SelectionKey を内部コレクションに追加して返します。パラメータはタイムアウトの設定に使用されます。
- selectedKeys();//内部コレクションからすべてのSelectionKeyを取得します。
3. 注意事項
NIO の ServerSocketChannel 関数は ServerSocket に似ており、SocketChannel 関数は Socket に似ています。 11. NIO を介した単純なサーバーとクライアントの通信1. サーバーpackage com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;public class NioServer {
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private static final int PORT = 8080;
public NioServer() {
try {
//获得选择器
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
//绑定端口
serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
//设置非阻塞模式
serverSocketChannel.configureBlocking(false);
//将该ServerSocketChannel 注册到selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
}catch (IOException e) {
System.out.println("NioServer error:"+e.getMessage());
}
}
public void listen() {
System.out.println("监听线程启动: " + Thread.currentThread().getName());
try {
while (true) {
int count = selector.select();
if(count > 0) {
//遍历得到selectionKey集合
Iterator<selectionkey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if(key.isAcceptable()) {
SocketChannel sc = serverSocketChannel.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
System.out.println(sc.getRemoteAddress() + " 上线 ");
}
//通道发送read事件,即通道是可读的状态
if(key.isReadable()) {
getDataFromChannel(key);
}
//当前的key 删除,防止重复处理
iterator.remove();
}
} else {
System.out.println("等待中");
}
}
}catch (Exception e) {
System.out.println("listen error:"+e.getMessage());
}
}
private void getDataFromChannel(SelectionKey key) {
SocketChannel channel = null;
try {
channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = channel.read(buffer);
//根据count的值做处理
if(count > 0) {
String msg = new String(buffer.array());
System.out.println("来自客户端: " + msg);
//向其它的客户端转发消息(排除自己)
sendInfoToOtherClients(msg, channel);
}
}catch (IOException e) {
try {
System.out.println(channel.getRemoteAddress() + " 离线了");
//取消注册
key.cancel();
}catch (IOException ex) {
System.out.println("getDataFromChannel error:"+ex.getMessage());
}
}finally {
try {
channel.close();
}catch (IOException ex) {
System.out.println("channel.close() error:"+ex.getMessage());
}
}
}
//转发消息给其它客户(通道)
private void sendInfoToOtherClients(String msg, SocketChannel self ) throws IOException{
System.out.println("服务器转发消息中...");
System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName());
//遍历 所有注册到selector 上的 SocketChannel,并排除 self
for(SelectionKey key: selector.keys()) {
Channel targetChannel = key.channel();
//排除自己
if(targetChannel instanceof SocketChannel && targetChannel != self) {
SocketChannel dest = (SocketChannel)targetChannel;
//将信息存储到buffer
ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
//将buffer数据写入通道
dest.write(buffer);
}
}
}
public static void main(String[] args) {
//创建服务器对象
NioServer nioServer = new NioServer();
nioServer.listen();
}}</selectionkey>
2. クライアントpackage com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Scanner;public class NioClient {
private final int PORT = 8080; //服务器端口
private Selector selector;
private SocketChannel socketChannel;
private String username;
public NioClient() throws IOException {
selector = Selector.open();
socketChannel = socketChannel.open(new InetSocketAddress("127.0.0.1", PORT));
//设置非阻塞
socketChannel.configureBlocking(false);
//将channel注册到selector
socketChannel.register(selector, SelectionKey.OP_READ);
username = socketChannel.getLocalAddress().toString().substring(1);
System.out.println(username + " is ok...");
}
//向服务器发送消息
public void sendInfo(String info) {
info = username + " 说:" + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
}catch (IOException e) {
System.out.println("sendInfo error:"+e.getMessage());
}
}
//读取从服务器端回复的消息
public void readInfo() {
try {
int readChannels = selector.select();
if(readChannels > 0) {
Iterator<selectionkey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if(key.isReadable()) {
//得到相关的通道
SocketChannel sc = (SocketChannel) key.channel();
//得到一个Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
//读取
sc.read(buffer);
//把读到的缓冲区的数据转成字符串
String msg = new String(buffer.array());
System.out.println(msg.trim());
}
}
iterator.remove(); //删除当前的selectionKey, 防止重复操作
} else {
System.out.println("没有可以用的通道...");
}
}catch (Exception e) {
System.out.println("readInfo error:"+e.getMessage());
}
}
public static void main(String[] args) throws Exception {
NioClient nioClient = new NioClient();
new Thread() {
public void run() {
while (true) {
nioClient.readInfo();
try {
Thread.currentThread().sleep(2000);
}catch (InterruptedException e) {
System.out.println("sleep error:"+e.getMessage());
}
}
}
}.start();
//发送数据给服务器端
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
nioClient.sendInfo(scanner.nextLine());
}
}}</selectionkey>
3. コンソール出力
## 推奨学習: 「
>>」
以上がJava NIO を完全にマスターできるようにします (概要の共有)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

この記事では、Javaプロジェクト管理、自動化の構築、依存関係の解像度にMavenとGradleを使用して、アプローチと最適化戦略を比較して説明します。

この記事では、MavenやGradleなどのツールを使用して、適切なバージョン化と依存関係管理を使用して、カスタムJavaライブラリ(JARファイル)の作成と使用について説明します。

この記事では、カフェインとグアバキャッシュを使用してJavaでマルチレベルキャッシュを実装してアプリケーションのパフォーマンスを向上させています。セットアップ、統合、パフォーマンスの利点をカバーし、構成と立ち退きポリシー管理Best Pra

この記事では、キャッシュや怠zyなロードなどの高度な機能を備えたオブジェクトリレーショナルマッピングにJPAを使用することについて説明します。潜在的な落とし穴を強調しながら、パフォーマンスを最適化するためのセットアップ、エンティティマッピング、およびベストプラクティスをカバーしています。[159文字]

Javaのクラスロードには、ブートストラップ、拡張機能、およびアプリケーションクラスローダーを備えた階層システムを使用して、クラスの読み込み、リンク、および初期化が含まれます。親の委任モデルは、コアクラスが最初にロードされ、カスタムクラスのLOAに影響を与えることを保証します


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター
