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();
                }
            }

        }

    }

}
时间: 2024-11-07 02:18:02

java nio之 channel通道(二)的相关文章

Java NIO中的通道Channel(二)分散/聚集 Scatter/Gather

什么是Scatter/Gather scatter/gather指的在多个缓冲区上实现一个简单的I/O操作,比如从通道中读取数据到多个缓冲区,或从多个缓冲区中写入数据到通道: scatter(分散):指的是从通道中读取数据分散到多个缓冲区Buffer的过程,该过程会将每个缓存区填满,直至通道中无数据或缓冲区没有空间: gather(聚集):指的是将多个缓冲区Buffer聚集起来写入到通道的过程,该过程类似于将多个缓冲区的内容连接起来写入通道: scatter/gather接口 如下是Scatte

Java NIO系列教程(二) Channel

原文地址:http://ifeve.com/channels/ 声明:Java NIO系列教材并非本人原创,只因阅读原文之后有感于文章之精妙,意欲与诸位共享,故而出此下策,忘原作者见谅.另附上原文地址. Java NIO的通道类似流,但又有些不同: 既可以从通道中读取数据,又可以写数据到通道.但流的读写通常是单向的. 通道可以异步地读写. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入. 正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道.如下图所示: C

java nio之channel

一.通道(Channel):由 java.nio.channels 包定义的.Channel 表示 IO 源与目标打开的连接.Channel 类似于传统的"流".只不过 Channel本身不能直接访问数据,Channel 只能与Buffer 进行交互. 二.Channel重要实现 FileChannel:操作文件的读写 SocketChannel:通过TCP读写网络数据 ServerSocketChannel:监听TCP连接,你能利用它创建一个最简单的Web服务器 DatagramCh

java NIO-Channel

基本简介 Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式. Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中. Java NIO: Non-blocking IO(非阻塞IO) Java

Java NIO(1)----Channel 和 Buffer

Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组件会在单独的章节中讲到. Channel 和 Buffer 基本上,所有的 IO 在NIO 中都从一个Channel 开始.Channel 有点

JAVA NIO 之Channel

缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.Channel 通道就是将数据传输给 ByteBuffer 对象或者从 ByteBuffer 对象获取数据进行传输. Channel 用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据.常用Channel有FileChannel.SocketChannel.DatagramChannel.ServerSocketChannelSocket 可以通过socket 通道的工厂方法直接创建.但是FileChan

Java NIO (2) Channel

Java NIO Channel Java NIO Channels are similar to streams with a few differences: You can both read and write to a Channels. Streams are typically one-way (read or write). Channels can be read and written asynchronously. Channels always read to, or w

Java NIO (5) Channel to Channel Transfers

Java NIO Channel to Channel Transfers In Java NIO you can transfer data directly from one channel to another, if one of the channels is a FileChannel. The FileChannel class has a transferTo() and a transferFrom() method which does this for you. trans

《JAVA NIO》Channel

1.类图 Channle主要分为两类:File操作对应的FIleChannel和Stream操作对应的socket的3个channel.问题:stream操作除了socket还有其他的吧?例如串口等 3.1.1打开通道通道可以以多种方式创建.Socket 通道有可以直接创建新socket 通道的工??方法.但是一个FileChannel 对象却只能通过在一个打开的RandomAccessFile.FileInputStream 或 FileOutputStream对象上调用getChannel(