1. 程式人生 > >java nio之channel

java nio之channel

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