BIO
BIO ==> Basic IO (基本IO), Block IO(阻塞IO)
Scanner操作,文件讀寫操作,Socket數據傳輸操作... 都是BIO
比如TPC羣聊,私聊聊天室
Socket涉及到的IO,也是BIO
資源浪費:
1. 多線程,每一個Socket會對應一個線程,如果用戶量巨大,會導致線程過
多,資源處理過多
2. 採用阻塞狀態,一旦進入阻塞,代碼無法執行其他操作。
3. 承載量一般,吞吐量比較小,同時可靠性不佳
2.2 NIO概述
NIO
NIO ==> New IO(新IO), Non-Block IO(非阻塞IO)
NIO非阻塞IO,運行當前程序在處理IO事務時,不會影響其他程序的運行,可以在不使用多線程的情況下,滿足IO操作要求。
三大核心部分:
通道
Channel
文件操作,網絡數據傳遞操作使用的通道
緩衝
Buffer
緩衝使用可以提供操作效率,減少不必要的讀寫次數
選擇器
Selector
真·核心 老大 boss
2.3 Buffer Channel完成文件操作
2.3.1 常用API
java.nio.Buffer
Buffer緩衝區
ByteBuffer 字節緩衝 常用
ShortBuffer
IntBuffer
LongBuffer
CharBuffer 字節緩衝 常用
FloatBuffer
DoubleBuffer
常用方法:
public static ByteBuffer allocate(int capacity);
按照指定的字節數分配對應的緩衝區空間,保存字節數據
public byte get();
從字節緩衝區對象中讀取一個byte類型數組
public final Buffer flip();
翻轉緩衝區,回到緩衝區的開始位置。
public static ByteBuffer wrap(byte[] arr);
存入一個byte類型數組到緩衝區,會得到一個新的ByteBuffer
public static ByteBuffer put(byte[] b);
將字節數組存入緩衝去
Channel接口,通道接口
FileChannel 文件操作通道
DatagramChannel UDP協議數據包操作的Channel
ServerSocketChannel TCP服務端ServerSocket對應Channel
SocketChannel TCP客戶端Socket對應Channel
首先操作文件,以FileChannel爲例
public long read(ByteBuffer buffer);
從通道中讀取數據到ByteBuffer中
public long write(ByteBuffer buffer);
從Buffer中寫數據到通道中
public long transferFrom(ReadableByteChannel src, long position, long count)
從指定srcChannel中,指定位置position開始,讀取count個元素,到當前通道中
文件複製操作。
public long transferTo(long position, long count, WritableByteChannel target)
將當前通道中的數據寫入到target中,從當前通道的position位置開始,計數count
Selector
選擇器,網絡編程使用NIO的大哥!!!
服務器可以執行一個線程,運行Selector程序,進行監聽操作。
新連接, 已經連接, 讀取數據,寫入數據
Selector常用方法:
public static Selector Open();
得到一個選擇器對象
public int select(long timeout);
監聽所有註冊通道,存在IO流操作是,會將對應的信息SelectionKey存入到內部的集
閤中,參數是一個超時時間
public Set<SelectionKey> selectionKeys();
返回當前Selector內部集合中保存的所有SelectionKey
2.4.2 SelectionKey
SelectionKey
表示Selector和網絡通道直接的關係
int OP_ACCEPT; 16 需要連接
int OP_CONNECT; 8 已經連接
int OP_READ; 1 讀取操作
int OP_WRITE; 4 寫入操作
SelectionKey
public abstract Selector selector();
得到與之關聯的 Selector 對象
public abstract SelectableChannel channel();
得到與之關聯的通道
public final Object attachment();
得到與之關聯的共享數據
public abstract SelectionKey interestOps(int ops);
設置或改變監聽事件
public final boolean isAcceptable();
是否可以 accept
public final boolean isReadable();
是否可以讀
public final boolean isWritable();
是否可以寫
2.4.3 ServerSocketChannel
ServerSocketChannel
服務端Socket程序對應的Channel通道
常用方法:
public static ServerSocketChannel open();
開啓服務器ServerSocketChannel通道,等於開始服務器程序
public final ServerSocketChannel bind(SocketAddress local);
設置服務器端端口號
public final SelectableChannel configureBlocking(boolean block);
設置阻塞或非阻塞模式, 取值 false 表示採用非阻塞模式
public SocketChannel accept();
[非阻塞]
獲取一個客戶端連接,並且得到對應的操作通道
public final SelectionKey register(Selector sel, int ops);
[重點方法]
註冊當前選擇器,並且選擇監聽什麼事件
2.4.4 SocketChannel
SocketChannel
客戶端Socket對應的Channel對象
常用方法:
public static SocketChannel open();
打卡一個Socket客戶端Channel對象
public final SelectableChannel configureBlocking(boolean block)
這裏可以設置是阻塞狀態,還是非阻塞狀態
false,表示非阻塞
public boolean connect(SocketAddress remote);
連接服務器
public boolean finishConnect();
如果connect連接失敗,可以通過finishConnect繼續連接
public int write(ByteBuffer buf);
寫入數據到緩衝流中
public int read(ByteBuffer buf); 、
從緩衝流中讀取數據
public final SelectionKey register(Selector sel, int ops, Object attechment);
註冊當前SocketChannel,選擇對應的監聽操作,並且可以帶有Object attachment參數
public final void close();
關閉SocketChannel