java nio之channel
阿新 • • 發佈:2017-12-01
host 不能 config wrap span bsp cal targe ext
一、通道(Channel):由 java.nio.channels 包定義的。Channel 表示 IO 源與目標打開的連接。Channel 類似於傳統的“流”。只不過 Channel本身不能直接訪問數據,Channel 只能與Buffer 進行交互。
二、Channel重要實現
- FileChannel:操作文件的讀寫
- SocketChannel:通過TCP讀寫網絡數據
- ServerSocketChannel:監聽TCP連接,你能利用它創建一個最簡單的Web服務器
- DatagramChannel:通過UDP讀寫網絡數據
三、FileChannel 的文件讀寫
1)利用FileChannel 本身提供的transferTo進行數據的讀寫。
package com.troy.nio.application; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.channels.FileChannel; public class Channel { public static void main(String[] args) throws Exception { //讀取文件 FileInputStream fileInputStream = new FileInputStream("d:/t.txt"); //寫出文件 FileOutputStream fileOutputStream = new FileOutputStream("d:/e.txt"); //獲取讀取通道 FileChannel inChannel = fileInputStream.getChannel(); //獲取寫入通道 FileChannel outChannel = fileOutputStream.getChannel(); //完成數據的寫入 inChannel.transferTo(0,inChannel.size(),outChannel); } }
2)利用FileChannel 提供的讀寫方法
package com.troy.nio.application; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class Channel { public static void main(String[] args) throws Exception { //讀取文件 FileInputStream fileInputStream = new FileInputStream("d:/t.txt"); //寫出文件 FileOutputStream fileOutputStream = new FileOutputStream("d:/e.txt"); //獲取讀取通道 FileChannel inChannel = fileInputStream.getChannel(); //獲取寫入通道 FileChannel outChannel = fileOutputStream.getChannel(); //緩存 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //讀取數據 while (inChannel.read(byteBuffer) != -1) { //轉換成可讀寫 byteBuffer.flip(); System.out.println(new String(byteBuffer.array(),"GBK").trim()); //寫出數據,清楚緩存 outChannel.write(byteBuffer); byteBuffer.clear(); } } }
四、SocketChannel和ServerSocketChannel在同時使用時,都是tcp協議進行傳輸的,在使用上面比較服務具體的協議控制
具體的應用可以參考:http://www.cnblogs.com/ll409546297/p/7929646.html
五、DatagramChannel的方式
1)客戶端
import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; public class UDPClient { public static void main(String[] args) throws Exception { //獲取UDP通道 DatagramChannel datagramChannel = DatagramChannel.open(); //設置非阻塞 datagramChannel.configureBlocking(false); //發送數據 datagramChannel.send(ByteBuffer.wrap("hello server!".getBytes()),new InetSocketAddress("localhost",9000)); } }
2)服務端的2中寫法,阻塞和非阻塞
1、阻塞
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; public class UDPServer { //UDP通道 private static DatagramChannel datagramChannel; public static void main(String[] args) throws Exception { serverInit(); listen(); } //初始化 private static void serverInit() throws IOException { //獲取UDP通道 datagramChannel = DatagramChannel.open(); //設置接收端口 datagramChannel.socket().bind(new InetSocketAddress(9000)); } //監聽 private static void listen() throws IOException { while (true) { //接收的長度 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //這裏會阻塞 datagramChannel.receive(byteBuffer); byteBuffer.flip(); System.out.println(new String(byteBuffer.array()).trim()); } } }
2、非阻塞,利用selector來進行數據選擇
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Iterator; public class UDPServer { //選擇器 private static Selector selector; //UDP通道 private static DatagramChannel datagramChannel; public static void main(String[] args) throws Exception { serverInit(); listen(); } //初始化 private static void serverInit() throws IOException { //獲取選擇器 selector = Selector.open(); //獲取UDP通道 datagramChannel = DatagramChannel.open(); //設置非阻塞 datagramChannel.configureBlocking(false); //設置接收端口 datagramChannel.socket().bind(new InetSocketAddress(9000)); //註冊 datagramChannel.register(selector, SelectionKey.OP_READ); } //監聽 private static void listen() throws IOException { while (true) { selector.select(); Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); if (selectionKey.isReadable()) { //接收的長度 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //這裏不會阻塞 datagramChannel.receive(byteBuffer); byteBuffer.flip(); System.out.println(new String(byteBuffer.array()).trim()); } } } } }
六、基本上channel的實現用法就這些了,但是裏面會涉及到很多細節的用法,這個需要自己進一步研究
java nio之channel