NIO框架(2)---Channel

上一次,我们总结了常用buffer种类和方法,这一次我们来总结一下常用的Channel,我们将Channel根据不同的用途分为三种:网络Channel,文件Channel,管道Channel

一. 网络Channel
名称描述
ServerSocketChannel监听socket流的channel
SocketChannel连接socket的channel
DatagramChannel使用datagram连接socket的Channel
AsynchronousServerSocketChannel监听socket流的channel(JDK7支持的AIO)
AsynchronousSocketChannel连接socket异步的channel(JDK7支持的AIO)

1. 对于ServerSocketChannel主要有open(),bind(SocketAddress),socket(),accept方法,接下来详细看一下方法的实现:

   public static ServerSocketChannel open() throws IOException {
    //可以看到open方法并没有在类中直接实现,而是通过静态代理的方式,在SelectorProvider中实现。
       return SelectorProvider.provider().openServerSocketChannel();
   }
   //绑定监听端口
    public abstract ServerSocketChannel bind(SocketAddress local, int backlog)
        throws IOException;
    //返回ServerSocket服务Socket
    public abstract ServerSocket socket();
    //接收Socket连接
    public abstract SocketChannel accept() throws IOException;

举一个简单使用的例子:

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.socket().bind(new InetSocketAddress(8888));
    while(true){
        SocketChannel socketChannel = serverSocketChannel.accept();
    }
  1. 接下来看一下SocketChannel的应用:
  InetSocketAddress socketAddress = new InetSocketAddress("localhost", 8080);  
  channel = SocketChannel.open(socketAddress);  
  channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
  ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建1024字节的缓冲  
  while (channel.read(buffer) != -1) {  
      buffer.flip();// flip方法在读缓冲区字节操作之前调用。  
      System.out.println(charset.decode(buffer));  
      // 使用Charset.decode方法将字节转换为字符串  
      buffer.clear();// 清空缓冲  
  }  

SocketChannel主要方法由read()和write()方法,以便将缓冲区内容读出和写入。

  1. DatagramChannel是可以收发UDP包的Channel

    DatagramChannel channel = DatagramChannel.open();
    // channel.socket().bind(new InetSocketAddress("localhost",8080));
    channel.connect(new InetSocketAddress("localhost",8080));
    ByteBuffer buf = ByteBuffer.allocate(1024);
    while(true){
        int read = channel.read(buf);
        break;
    }
    channel.write(buf);

4.AsynchronousServerSocketChannel作为异步非阻塞的Channel,提供了异步的接收连接,来看一下方法定义:

 public abstract Future<AsynchronousSocketChannel> accept();

通过方法定义我们可以看到AsynchronousServerSocketChannel使用Future来接收连接,使用Future的get()方法返回Channel。

  1. AsynchronousSocketChannel作为对应SocketChannel的异步Channel,同样提供了异步的连接、读和写方法:
 public abstract Future<Void> connect(SocketAddress remote);
 public abstract Future<Integer> read(ByteBuffer dst);
 public abstract Future<Integer> write(ByteBuffer src);
二. 文件Channel
名称描述
FileChannel支持读、写、映射以及操作文件的管道
AsynchronousFileChannel支持异步读、写、映射以及操作文件的管道(JDK7支持的AIO)

1. FileChannel支持读写文件,主要方法同样是read(Buffer)和write(Buffer),举个例子:

```
//1.打开文件
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
//2.读取文件
ByteBuffer buf = ByteBuffer.allocate(100);
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = null;
while(inChannel.read(buf) != -1){
    buf.flip();
    charBuffer = decoder.decode(buf);
    System.out.print(charBuffer.toString());   
    buf.clear();
}
//3.写入文件
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
    channel.write(buf);
}
//4.关闭
channel.close();
```
三. 管道Channel

PipeChannel拥有两个管道如下:

名称描述
Pipe.SinkChannelPipe的目的Channel
Pipe.SourceChannelPipe的输入Channel

SourceChannel相当于管道的头,SinkChannel相当于管道的尾,接下来看一个读写的例子:

    public class PipeChannelTest {
        public static void main(String[] args) {
            try {
                Pipe pipe = Pipe.open();
                SourceChannel source = pipe.source();
                SinkChannel sink = pipe.sink();

                writeData(sink,"Hello World!");
                readData(source);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        private static void readData(SourceChannel source) {
            ByteBuffer buffer = ByteBuffer.allocate(48);
            Charset charset = Charset.forName("UTF-8");
            CharBuffer charBuf = null;
            try {
                while(source.read(buffer)!=-1){
                    buffer.flip();
                    charBuf = charset.decode(buffer);
                    System.out.println(charBuf.toString());
                    buffer.clear();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public static void writeData(SinkChannel sink, String data) throws IOException {
            if(data== null)
                throw new NullPointerException();
            ByteBuffer buf = ByteBuffer.allocate(48);
            buf.clear();
            buf.put(data.getBytes());
            buf.flip();
            while(buf.hasRemaining()) {
                sink.write(buf);
            }
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值