1 /* 2 * 客戶端發送數據 經過channel通道 3 * */ 4 @Test 5 public void Client() throws IOException { 6 7 //獲取channel通道 並設置主機號和端口號 8 SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8080)); 9 10 //由於使用非阻塞NIO 因此必須切換爲非阻塞 11 socketChannel.configureBlocking(false); //默認爲true 須要改成非堵塞的 12 13 //開闢緩衝區進行存儲數據 14 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); 15 16 //準備工做就緒後,準備發送數據給服務端 17 //打印當前日期轉爲Byte數據傳出 18 byteBuffer.put(new Date().toString().getBytes()); 19 //切換讀寫模式 20 byteBuffer.flip(); 21 //寫入通道 22 socketChannel.write(byteBuffer); 23 //完畢時,清除緩衝區內容 24 byteBuffer.clear(); 25 26 //==================== 27 //關閉相關流 28 socketChannel.close(); 29 30 }
LocalDateTime.now().toString().getBytes() //轉爲Byte字節
1 public static SocketChannel open(SocketAddress remote) 2 throws IOException 3 { 4 SocketChannel sc = open(); 5 try { 6 sc.connect(remote); //打開一個新的channel時,綁定鏈接到主機和端口上 7 } catch (Throwable x) { 8 try { 9 sc.close(); //異常時關閉鏈接 10 } catch (Throwable suppressed) { 11 x.addSuppressed(suppressed); 12 } 13 throw x; 14 } 15 assert sc.isConnected(); 16 return sc; 17 }
*/ public InetSocketAddress(String hostname, int port) { checkHost(hostname); //檢查主機號是否爲空 爲空返回異常。 InetAddress addr = null; String host = null; try { addr = InetAddress.getByName(hostname); } catch(UnknownHostException e) { host = hostname; } holder = new InetSocketAddressHolder(host, addr, checkPort(port)); //檢查端口。 }
//檢查端口方法
private static int checkPort(int port) {
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException("port out of range:" + port);
return port;
}
//檢查主機號方法
private static String checkHost(String hostname) {
if (hostname == null)
throw new IllegalArgumentException("hostname can't be null");
return hostname;
}
1 /* 2 * 服務端接收客戶端傳來的數據 3 * */ 4 @Test 5 public void server() throws IOException { 6 7 //獲取channel通道 8 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 9 //切換爲非堵塞狀態 10 serverSocketChannel.configureBlocking(false); 11 //分配服務端的緩衝區 12 ByteBuffer serverByteBuffer = ByteBuffer.allocate(1024); 13 //將客戶端的InetSocketAddress綁定到通道,不綁定 不統一將獲取不到數據 14 serverSocketChannel.bind(new InetSocketAddress(8080)); 15 //獲取選擇器 16 Selector selector = Selector.open(); 17 //將通道註冊到選擇器中,而且制定監聽方式 18 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); 19 //進行輪詢選擇器上就緒成功的事件 當存在就緒成功的及進行下一步 20 while (selector.select() > 0){ 21 //對已存在的就緒事件進行迭代 22 Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator(); 23 24 //有元素就進行下一步 25 while (selectionKeyIterator.hasNext()){ 26 //獲取到就緒事件 27 SelectionKey next = selectionKeyIterator.next(); 28 29 //對獲取到的就緒事件判斷是何種類型 30 if (next.isAcceptable()){ 31 32 //獲取鏈接 33 SocketChannel accept = serverSocketChannel.accept(); 34 35 //將獲取到的鏈接切換爲非堵塞模式 36 accept.configureBlocking(false); 37 38 //將獲取到的連接 註冊金selector 39 accept.register(selector,SelectionKey.OP_READ); 40 41 //判斷是否準備好讀 42 }else if (next.isReadable()){ 43 44 //獲取已就緒的通道 45 SocketChannel channel = (SocketChannel) next.channel(); 46 47 //分配緩衝區 48 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); 49 50 //讀取數據 51 int length = 0 ; 52 while ((length = channel.read(byteBuffer)) > 0){ 53 byteBuffer.flip(); 54 System.out.println(new String(byteBuffer.array(),0,length)); 55 byteBuffer.clear(); 56 } 57 58 59 } 60 61 //完成傳輸須要取消選擇鍵,防止下次出問題 62 selectionKeyIterator.remove(); 63 64 } 65 } 66 67 68 }
Selector selector = Selector.open();
public static Selector open() throws IOException { return SelectorProvider.provider().openSelector(); } //首先進入此方法判斷是否存在選擇器 public static SelectorProvider provider() { synchronized (lock) { if (provider != null) //第一次爲false return provider; return AccessController.doPrivileged( new PrivilegedAction<SelectorProvider>() { public SelectorProvider run() { if (loadProviderFromProperty()) return provider; if (loadProviderAsService()) return provider; provider = sun.nio.ch.DefaultSelectorProvider.create(); return provider; } }); } }
//false時 跳入以下方法。
public static ServerSocketChannel open() throws IOException {
return SelectorProvider.provider().openServerSocketChannel();
}
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //可多選監聽操做項
Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();
selectionKeyIterator.next()
selectionKeyIterator.remove();
public static void main(String[] args) throws IOException { //獲取channel通道 並設置主機號和端口號 SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8080)); //由於使用非阻塞NIO 因此必須切換爲非阻塞 socketChannel.configureBlocking(false); //開闢緩衝區進行存儲數據 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //附加輸入: Scanner scanner = new Scanner(System.in); //經過控制檯鍵入數據 while (scanner.hasNext()){ String str = scanner.next(); //準備工做就緒後,準備發送數據給服務端 //打印當前日期轉爲Byte數據傳出 byteBuffer.put((new Date().toString()+":--->"+str).getBytes()); //切換讀寫模式 byteBuffer.flip(); //寫入通道 socketChannel.write(byteBuffer); //完畢時,清除緩衝區內容 byteBuffer.clear(); } }
//完成傳輸須要取消選擇鍵,防止下次出問題
selectionKeyIterator.remove();