java nio之 channel通道

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java nio之 channel通道相关的知识,希望对你有一定的参考价值。


java nio 通道上一篇文章里就讲述过,channel总是写数据的时候,要先把数据写入到bytebuffer,读数据的时候总是要先从channel中读入到bytebuffer。如下图,这个图是好多知名博客常用的图,很好理解这个channel。

技术分享


channel分为一下几种:

  1. FileChannel

  2. SocketChannel

  3. ServerSocketChannel

  4. DatagramChannel


FileChannel:

经常说的FileChannel都是拿下面的例子说事

代码如下:

package com.nio.basic;

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Created by sdc on 2017/8/13.
 */
public class RandomAccessFileTest {

    public static void main(String[] args) {
        readFile();
    }

    /**
     * 读取文件
     * @throws Exception
     */
    public static void readFile(){
        String fileName = "C:\\Users\\sdc\\Desktop\\gc (2).log";
        RandomAccessFile randomAccessFile = null;
        try{
            randomAccessFile = new RandomAccessFile(fileName, "r");
            long fileLength = randomAccessFile.length();
            System.out.print("length" + fileLength);

            int start = 100;
            randomAccessFile.seek(start);
            byte[] bytes = new byte[20];
            int read = 0;
            while ((read = randomAccessFile.read(bytes)) != -1) {
                System.out.println(new String(bytes, "UTF-8"));
            }

            System.out.println(bytes.length);
            System.out.println(new String(bytes, "UTF-8"));

        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (randomAccessFile != null) {
                try {
                    randomAccessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}


还有这样的例子:

FileInputStream is = new FileInputStream(new File(src));
FileChannel channelFrom = is.getChannel();

其实这两个是用到了nio的channel,不妨自己写一个例子试试。


SocketChannel和ServerSocketChannel一般是两个集合起来说的,一个用于客户端连接,一个用于服务端连接。

package com.nio.basic;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * nio 服务端
 * Created by sdc on 2017/8/13.
 */
public class Nioserver {

    ByteBuffer buffer = ByteBuffer.allocate(1024);

    public static void main(String[] args) throws IOException {
        System.out.println("server started...");
        try {
            new NIoServer().run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run () throws  Exception {
        //打开服务器端的套接字通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //服务器端设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //服务端进行绑定
        serverSocketChannel.bind(new InetSocketAddress("localhost", 8000));

        //注册感兴趣的事件
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int selectCount = selector.select();
            if( selectCount ==0 ) {
                continue;
            }

            selector.select();
            Set<SelectionKey> keys = selector.selectedKeys();
            //获取迭代器
            Iterator<SelectionKey> keyIterator = keys.iterator();

            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (!key.isValid()) {
                    continue;
                }
                if (key.isAcceptable()) {
                    ServerSocketChannel  sscTemp = (ServerSocketChannel) key.channel();
                    //得到一个连接好的SocketChannel,并把它注册到Selector上,兴趣操作为READ
                    SocketChannel socketChannel = sscTemp.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("REGISTER CHANNEL , CHANNEL NUMBER IS:" + selector.keys().size());
                } else if (key.isReadable()) {
                    //读取通道中的数据
                    SocketChannel channel = (SocketChannel) key.channel();
                    read(channel);
                }
                keyIterator.remove(); //该事件已经处理,可以丢弃
            }
        }
    }

    private void read(SocketChannel channel) throws IOException {
        int count ;
        buffer.clear();
        try {
            while ((count = channel.read(buffer)) > 0) {
                buffer.flip();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                System.out.println("READ FROM CLIENT:" + new String(bytes));
            }
            if (count < 0) {
                channel.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}
package com.nio.basic;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * nio 客户端
 * Created by sdc on 2017/8/13.
 */
public class NioClient {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(new Client("nio-client-1"));
        executorService.submit(new Client("nio-client-2"));
        executorService.submit(new Client("nio-client-3"));
        executorService.shutdown();
    }

    static class Client extends Thread {

        private String clientThreadName;

        ByteBuffer buffer = ByteBuffer.allocate(1024);

        Random random = new Random(20);

        Client(String clientThreadName) {
            this.clientThreadName = clientThreadName;
        }

        @Override
        public void run() {
            SocketChannel channel = null;
            try {
                channel = SocketChannel.open();
                channel.configureBlocking(false);
                channel.connect(new InetSocketAddress("localhost", 8000));
                while (!channel.finishConnect()) {
                    TimeUnit.MICROSECONDS.sleep(100);
                }

                for (int i=0; i<5; i++) {
                    TimeUnit.MICROSECONDS.sleep(100 * random.nextInt());
                    String message = "send message " + i + " from" + clientThreadName;
                    buffer.put(message.getBytes());
                    buffer.flip();

                    //buffer先把数据读入到buffer,然后channel先把buffer中的数据写入到channel,
                    channel.write(buffer);

                    buffer.clear();
                }

            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }


}




本文出自 “不积跬步无以至千里” 博客,请务必保留此出处http://shangdc.blog.51cto.com/10093778/1955874

以上是关于java nio之 channel通道的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO 之 Channel(通道)

Java NIO 之 Channel(通道)

java的nio之:java的nio系列教程之channel的数据交换

NIO核心之Channel通道

java nio之 channel通道

Java基础知识强化之IO流笔记76:NIO之 Channel(通道)之间的数据传输