Buffer:java
最大容量是下標減一編程
Buffer的使用--數據變化過程,數據讀寫方式。
安全
SelectionKey的四種就緒狀態常量:Connect、Accept、Read、Write。
有價值的屬性:經過SelectionKey集合獲取當前的Channel,Select對象、該Channel已就緒事件集合和所關心事件集合。服務器
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Set; /** * NIO服務器端 */ public class NioServer { /** * 啓動 */ public void start() throws IOException { /** * 1. 建立Selector */ Selector selector = Selector.open(); /** * 2. 經過ServerSocketChannel建立channel通道 */ ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); /** * 3. 爲channel通道綁定監聽端口 */ serverSocketChannel.bind(new InetSocketAddress(8000)); /** * 4. **設置channel爲非阻塞模式** */ serverSocketChannel.configureBlocking(false); /** * 5. 將channel註冊到selector上,監聽鏈接事件 */ serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("服務器啓動成功!"); /** * 6. 循環等待新接入的鏈接 */ for (;;) { // while(true) c for;; /** * TODO 獲取可用channel數量 */ int readyChannels = selector.select(); /** * TODO 爲何要這樣!!? */ if (readyChannels == 0) continue; /** * 獲取可用channel的集合 */ Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator iterator = selectionKeys.iterator(); while (iterator.hasNext()) { /** * selectionKey實例 */ SelectionKey selectionKey = (SelectionKey) iterator.next(); /** * **移除Set中的當前selectionKey** */ iterator.remove(); /** * 7. 根據就緒狀態,調用對應方法處理業務邏輯 */ /** * 若是是 接入事件 */ if (selectionKey.isAcceptable()) { acceptHandler(serverSocketChannel, selector); } /** * 若是是 可讀事件 */ if (selectionKey.isReadable()) { readHandler(selectionKey, selector); } } } } /** * 接入事件處理器 */ private void acceptHandler(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { /** * 若是要是接入事件,建立socketChannel */ SocketChannel socketChannel = serverSocketChannel.accept(); /** * 將socketChannel設置爲非阻塞工做模式 */ socketChannel.configureBlocking(false); /** * 將channel註冊到selector上,監聽 可讀事件 */ socketChannel.register(selector, SelectionKey.OP_READ); /** * 回覆客戶端提示信息 */ socketChannel.write(Charset.forName("UTF-8") .encode("你與聊天室裏其餘人都不是朋友關係,請注意隱私安全")); } /** * 可讀事件處理器 */ private void readHandler(SelectionKey selectionKey, Selector selector) throws IOException { /** * 要從 selectionKey 中獲取到已經就緒的channel */ SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); /** * 建立buffer */ ByteBuffer byteBuffer = ByteBuffer.allocate(1024); /** * 循環讀取客戶端請求信息 */ String request = ""; while (socketChannel.read(byteBuffer) > 0) { /** * 切換buffer爲讀模式 */ byteBuffer.flip(); /** * 讀取buffer中的內容 */ request += Charset.forName("UTF-8").decode(byteBuffer); } /** * 將channel再次註冊到selector上,監聽他的可讀事件 */ socketChannel.register(selector, SelectionKey.OP_READ); /** * 將客戶端發送的請求信息 廣播給其餘客戶端 */ if (request.length() > 0) { // 廣播給其餘客戶端 broadCast(selector, socketChannel, request); } } /** * 廣播給其餘客戶端 */ private void broadCast(Selector selector, SocketChannel sourceChannel, String request) { /** * 獲取到全部已接入的客戶端channel */ Set<SelectionKey> selectionKeySet = selector.keys(); /** * 循環向全部channel廣播信息 */ selectionKeySet.forEach(selectionKey -> { Channel targetChannel = selectionKey.channel(); // 剔除發消息的客戶端 if (targetChannel instanceof SocketChannel && targetChannel != sourceChannel) { try { // 將信息發送到targetChannel客戶端 ((SocketChannel) targetChannel).write( Charset.forName("UTF-8").encode(request)); } catch (IOException e) { e.printStackTrace(); } } }); } /** * 主方法 * @param args */ public static void main(String[] args) throws IOException { new NioServer().start(); } }
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Scanner; /** * NIO客戶端 */ public class NioClient { /** * 啓動 */ public void start(String nickname) throws IOException { /** * 鏈接服務器端 */ SocketChannel socketChannel = SocketChannel.open( new InetSocketAddress("127.0.0.1", 8000)); /** * 接收服務器端響應 */ // 新開線程,專門負責來接收服務器端的響應數據 // selector , socketChannel , 註冊 Selector selector = Selector.open(); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); new Thread(new NioClientHandler(selector)).start(); /** * 向服務器端發送數據 */ Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { String request = scanner.nextLine(); if (request != null && request.length() > 0) { socketChannel.write( Charset.forName("UTF-8") .encode(nickname + " : " + request)); } } } public static void main(String[] args) throws IOException { // new NioClient().start(); } }
import java.io.IOException; public class AClient { public static void main(String[] args) throws IOException { new NioClient().start("A/B/C Client"); } }