昨天看了hadoop代码,貌似前段时间看的NIO都忘完了。这里附上前段时间写的基于NIO的 socketServer和client的代码。并在这里多嘴几句,加深记忆:
BIO:1.4以前 阻塞IO
NIO:1.4-1.7 其中有基于channel的非阻塞IO 和 selector的多路复用IO
AIO :1.7 异步IO
这上面估计就是这几种IO的区别了。。。。
还有就是这张图,,顺便附上一个连接 以后可以学习AIO:http://colobu.com/2014/11/13/java-aio-introduction/
Server端:
package com.NIO; import java.io.ByteArrayOutputStream; 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; import java.util.logging.Logger; /** * NIO服务端 * * @author shirdrn */ public class SelectorFirst extends Thread { private static final Logger log = Logger.getLogger(SelectorFirst.class.getName()); private InetSocketAddress inetSocketAddress; private Handler handler = new ServerHandler(); public SelectorFirst(String hostname, int port) { inetSocketAddress = new InetSocketAddress(hostname, port); } @Override public void run() { try { Selector selector = Selector.open(); // 打开选择器 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 打开通道 serverSocketChannel.configureBlocking(false); // 非阻塞 serverSocketChannel.socket().bind(inetSocketAddress); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 向通道注册选择器和对应事件标识 log.info("Server: socket server started."); while(true) { // 轮询 int nKeys = selector.select(); if(nKeys>0) { Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> it = selectedKeys.iterator(); while(it.hasNext()) { SelectionKey key = it.next(); if(key.isAcceptable()) { log.info("Server: SelectionKey is acceptable."); handler.handleAccept(key); } else if(key.isReadable()) { log.info("Server: SelectionKey is readable."); handler.handleRead(key); } else if(key.isWritable()) { log.info("Server: SelectionKey is writable."); handler.handleWrite(key); } it.remove(); } } } } catch (IOException e) { e.printStackTrace(); } } /** * 简单处理器接口 * * @author shirdrn */ interface Handler { /** * 处理{@link SelectionKey#OP_ACCEPT}事件 * @param key * @throws IOException */ void handleAccept(SelectionKey key) throws IOException; /** * 处理{@link SelectionKey#OP_READ}事件 * @param key * @throws IOException */ void handleRead(SelectionKey key) throws IOException; /** * 处理{@link SelectionKey#OP_WRITE}事件 * @param key * @throws IOException */ void handleWrite(SelectionKey key) throws IOException; } /** * 服务端事件处理实现类 * * @author shirdrn */ class ServerHandler implements Handler { @Override public void handleAccept(SelectionKey key) throws IOException { ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); log.info("Server: accept client socket " + socketChannel); socketChannel.configureBlocking(false); socketChannel.register(key.selector(), SelectionKey.OP_READ); } @Override public void handleRead(SelectionKey key) throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(5); SocketChannel socketChannel = (SocketChannel)key.channel(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bytes; int size = 0; while((size =socketChannel.read(byteBuffer))>0){ byteBuffer.flip(); bytes = new byte[size]; byteBuffer.get(bytes); log.info("Server: data = " + new String(byteBuffer.array(), 0, size)); baos.write(bytes); byteBuffer.clear(); } bytes = baos.toByteArray(); ByteBuffer buffer = ByteBuffer.allocate(5); socketChannel.write(buffer.wrap("caonima\nshibushi".getBytes())); /*while(true) { int readBytes = socketChannel.read(byteBuffer); if(readBytes>0) { log.info("Server: readBytes = " + readBytes); log.info("Server: data = " + new String(byteBuffer.array(), 0, readBytes)); byteBuffer.flip(); socketChannel.write(byteBuffer); } // break; }*/ socketChannel.close(); } @Override public void handleWrite(SelectionKey key) throws IOException { ByteBuffer byteBuffer = (ByteBuffer) key.attachment(); byteBuffer.flip(); SocketChannel socketChannel = (SocketChannel)key.channel(); socketChannel.write(byteBuffer); if(byteBuffer.hasRemaining()) { key.interestOps(SelectionKey.OP_READ); } byteBuffer.compact(); } } public static void main(String[] args) { SelectorFirst server = new SelectorFirst("localhost", 1000); server.start(); } }
Client端
package com.NIO; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.logging.Logger; /** * NIO客户端 * * @author shirdrn */ public class Client { private static final Logger log = Logger.getLogger(Client.class.getName()); private InetSocketAddress inetSocketAddress; public Client(String hostname, int port) { inetSocketAddress = new InetSocketAddress(hostname, port); } /** * 发送请求数据 * @param requestData */ public void send(String requestData) { try { SocketChannel socketChannel = SocketChannel.open(inetSocketAddress); socketChannel.configureBlocking(false); ByteBuffer byteBuffer = ByteBuffer.allocate(512); socketChannel.write(ByteBuffer.wrap(requestData.getBytes())); while (true) { byteBuffer.clear(); int readBytes = socketChannel.read(byteBuffer); if (readBytes > 0) { byteBuffer.flip(); log.info("Client: readBytes = " + readBytes); log.info("Client: data = " + new String(byteBuffer.array(), 0, readBytes)); socketChannel.close(); break; } } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { String hostname = "localhost"; String requestData = "Actions speak louder than words!\n" + " but you cant see"; int port = 1000; new Client(hostname, port).send(requestData); } }