Java NIO之Channel

今天來談一談NIO中的Channel,上一篇文章介紹了Buffer,有了Buffer還須要有一個通道來處理Buffer。它就是今天咱們要學習的Channel。按照字面理解,它就是一個通道,能夠從通道中讀數據,也能夠把數據寫入到通道中。git

Channel能夠分爲幾大類github

  • FileChannel(文件操做)
  • SocketChannel(客戶端TCP操做)
  • ServerSocketChannel(服務端TCP操做)
  • DatagramChannel(UDP操做)

FileChannel

FileChannel比較簡單,主要用於文件操做。在使用FileChannel以前,須要先打開它。FileChannel是不能設置非阻塞的,咱們能夠經過RandomAccessFile來獲取一個FileChannel的對象RandomAccessFilegetChannel()方法bash

public final FileChannel getChannel() {
    synchronized (this) {
        if (channel == null) {
            channel = FileChannelImpl.open(fd, path, true, rw, this);
        }
        return channel;
    }
}
複製代碼

有了FileChannel就能夠對文件進行讀寫了,咱們分別看一下讀寫的代碼。微信

read

首先把文件中的數據從channel中讀出來,而後寫入到咱們分配的buffer裏,而後再把buffer中的數據打印出來,代碼以下:dom

ByteBuffer buffer = ByteBuffer.allocate(100);
// fileChannel中讀出來,寫到buffer中
int read = fileChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
	System.out.print((char) buffer.get());
}
複製代碼

write

首先把要寫入的內容放入buffer裏,而後經過channel把buffer中的數據寫入到文件中,當咱們再查看文件的時候,就有寫入以後的內容了,代碼以下:socket

String str = " is best";
buffer.clear();
buffer.put(str.getBytes());
buffer.flip();
// 從buffer中讀出來,經過channel寫入到文件中
while (buffer.hasRemaining()) {
	fileChannel.write(buffer);
}
複製代碼

close

使用完channel後關閉channel。學習

fileChannel.close();
複製代碼

SocketChannel&ServerSocketChannel

SocketChannel和ServerSocketChannel主要用於TCP鏈接。SocketChannel用於客戶端,ServerSocketChannel用於服務端,客戶端和服務端通訊以前首先要創建鏈接。ui

創建鏈接

客戶端

客戶端創建鏈接的過程,首先打開SocketChannel,而後鏈接到服務端,代碼以下:this

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8000));
複製代碼

服務端

服務端首先打開ServerSocketChannel,而後綁定一個端口,代碼以下:spa

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(8000));
複製代碼

發送接收數據

客戶端

鏈接創建成功以後,客戶端就能夠給服務端發送數據了,和FileChannel同樣,首先要把數據放到buffer中,而後再寫到channel裏。

//鏈接是否創建成功
boolean isConnect = socketChannel.isConnected();

ByteBuffer buffer = ByteBuffer.allocate(128);
buffer.clear();
buffer.put(("qiwoo").getBytes());

buffer.flip();
while (buffer.hasRemaining()) {
	socketChannel.write(buffer);
}

複製代碼

服務端

服務端ServerSocketChannel收到鏈接請求時,返回一個SocketChannel對象。而後就能夠把數據從channel中讀出來,而後寫入到buffer裏。

SocketChannel socketChannel = serverSocketChannel.accept();

ByteBuffer buffer = ByteBuffer.allocate(128);
socketChannel.read(buffer);

buffer.flip();

while (buffer.hasRemaining()) {
	System.out.println((char) buffer.get());
}
複製代碼

DatagramChannel

DatagramChannel,使用UDP協議來進行傳輸。因爲不須要創建鏈接,其實沒有客戶端服務端的概念,爲了便於理解,咱們定義其中一端爲客戶端,一端爲服務端。

Bind端口

客戶端

打開DatagramChannel,而後綁定一個端口

DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.socket().bind(new InetSocketAddress(8888));
複製代碼

服務端

打開DatagramChannel,而後綁定一個端口

DatagramChannel datagramChannel = DatagramChannel.open();
datagramChannel.socket().bind(new InetSocketAddress(8889));
複製代碼

發送接收數據

發送和接收數據也比較簡單,代碼以下:

客戶端

ByteBuffer buffer = ByteBuffer.allocate(100);

buffer.put("qiwoo".getBytes());
buffer.flip();

InetAddress address = InetAddress.getLocalHost();
datagramChannel.send(buffer, new InetSocketAddress(address, 8889));
複製代碼

服務端

ByteBuffer buffer = ByteBuffer.allocate(100);
buffer.clear();
datagramChannel.receive(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
	System.out.print((char) buffer.get());
}
複製代碼

本文demo

關注微信公衆號,最新技術乾貨實時推送

image
相關文章
相關標籤/搜索