demo
public static void method1(){ RandomAccessFile aFile = null; try{ aFile = new RandomAccessFile("src/nio.txt","rw"); FileChannel fileChannel = aFile.getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024); int bytesRead = fileChannel.read(buf); System.out.println(bytesRead); while(bytesRead != -1) { buf.flip(); while(buf.hasRemaining()) { System.out.print((char)buf.get()); } buf.compact(); bytesRead = fileChannel.read(buf); } }catch (IOException e){ e.printStackTrace(); }finally{ try{ if(aFile != null){ aFile.close(); } }catch (IOException e){ e.printStackTrace(); } } }
分析
从案例2中可以总结出使用Buffer一般遵循下面几个步骤:
- 分配空间(ByteBuffer buf = ByteBuffer.allocate(1024); 还有一种allocateDirector后面再陈述)
- 写入数据到Buffer(int bytesRead = fileChannel.read(buf);)
- 调用filp()方法( buf.flip();)
- 从Buffer中读取数据(System.out.print((char)buf.get());)
- 调用clear()方法或者compact()方法
Buffer顾名思义:缓冲区,实际上是一个容器,一个连续数组。Channel提供从文件、网络读取数据的渠道,但是读写的数据都必须经过Buffer。如下图:
向Buffer中写数据:
- 从Channel写到Buffer (fileChannel.read(buf))
- 通过Buffer的put()方法 (buf.put(…))
从Buffer中读取数据:
- 从Buffer读取到Channel (channel.write(buf))
- 使用get()方法从Buffer中读取数据 (buf.get())
可以把Buffer简单地理解为一组基本数据类型的元素列表,它通过几个变量来保存这个数据的当前位置状态:capacity, position, limit, mark:
Selector简介
服务端
public class ServerSocketChannelTest { private int size = 1024; private ServerSocketChannel socketChannel; private ByteBuffer byteBuffer; private Selector selector; private final int port = 8998; private int remoteClientNum=0; public ServerSocketChannelTest() { try { initChannel(); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } public void initChannel() throws Exception { socketChannel = ServerSocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.bind(new InetSocketAddress(port)); System.out.println("listener on port:" + port); selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_ACCEPT); byteBuffer = ByteBuffer.allocateDirect(size); byteBuffer.order(ByteOrder.BIG_ENDIAN); } private void listener() throws Exception { while (true) { int n = selector.select(); if (n == 0) { continue; } Iteratorite = selector.selectedKeys().iterator(); while (ite.hasNext()) { SelectionKey key = ite.next(); //a connection was accepted by a ServerSocketChannel. if (key.isAcceptable()) { ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel channel = server.accept(); registerChannel(selector, channel, SelectionKey.OP_READ); remoteClientNum++; System.out.println("online client num="+remoteClientNum); replyClient(channel); } //a channel is ready for reading if (key.isReadable()) { readDataFromSocket(key); } ite.remove();//must } } } protected void readDataFromSocket(SelectionKey key) throws Exception { SocketChannel socketChannel = (SocketChannel) key.channel(); int count; byteBuffer.clear(); while ((count = socketChannel.read(byteBuffer)) > 0) { byteBuffer.flip(); // Make buffer readable // Send the data; don't assume it goes all at once while (byteBuffer.hasRemaining()) { socketChannel.write(byteBuffer); } byteBuffer.clear(); // Empty buffer } if (count < 0) { socketChannel.close(); } } private void replyClient(SocketChannel channel) throws IOException { byteBuffer.clear(); byteBuffer.put("hello client!\r\n".getBytes()); byteBuffer.flip(); channel.write(byteBuffer); } private void registerChannel(Selector selector, SocketChannel channel, int ops) throws Exception { if (channel == null) { return; } channel.configureBlocking(false); channel.register(selector, ops); } public static void main(String[] args) { try { new ServerSocketChannelTest().listener(); } catch (Exception e) { e.printStackTrace(); } }}
客户端代码:
public class SocketChannelTest { private int size = 1024; private ByteBuffer byteBuffer; private SocketChannel socketChannel; public void connectServer() throws IOException { socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress("127.0.0.1", 8998)); byteBuffer = ByteBuffer.allocate(size); byteBuffer.order(ByteOrder.BIG_ENDIAN); receive(); } private void receive() throws IOException { while (true) { int count; byteBuffer.clear(); while ((count = socketChannel.read(byteBuffer)) > 0) { byteBuffer.flip(); while (byteBuffer.hasRemaining()) { System.out.print((char) byteBuffer.get()); } //send("send data to server\r\n".getBytes()); byteBuffer.clear(); } } } private void send(byte[] data) throws IOException { byteBuffer.clear(); byteBuffer.put(data); byteBuffer.flip(); socketChannel.write(byteBuffer); } public static void main(String[] args) throws IOException { new SocketChannelTest().connectServer(); }}