入门:初探NIO原理及使用
//Socket服务器端public class NIOServer03 { public static void main(String[] args) throws IOException { //创建选择器(多路复用器)对象 Selector selector = Selector.open(); //创建Socket服务端通道对象 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //配置为非阻塞 serverSocketChannel.configureBlocking(false); //将Socket服务端通道的对象注册到选择器上,并指定其通道对象的注册事件为接收事件 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //指定Socket服务端的IP地址和端口 InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888); //绑定地址 serverSocketChannel.bind(address); //服务端需要一直建立连接保存与客户端通讯,所以这里设为死循环 while(true){ //开启选择器进行监听,这里至少选择一个通道,如果该选择器是关闭抛出ClosedSelectorException selector.select(); //返回此选择器的选定键集(注册的事件)。如果该选择器是关闭抛出ClosedSelectorException Set<SelectionKey> selectionKeys = selector.selectedKeys(); //用迭代器遍历选定键集 Iterator<SelectionKey> keyIterator = selectionKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); //如果key的注册事件为接收事件时执行 if(key.isAcceptable()){ //返回为其创建此密钥(key)的通道 ServerSocketChannel socketChannelByKey = (ServerSocketChannel) key.channel(); /*** 接收与此通道的套接字建立的连接* 如果没有挂起的连接,会立即返回null,否则它将无限期阻塞,直到有新连接或发生I/O错误* 返回新连接的套接字通道*/ SocketChannel socketChannel = socketChannelByKey.accept(); //设为非阻塞 socketChannel.configureBlocking(false); //将该套接字通道注册为读取事件 socketChannel.register(selector, SelectionKey.OP_READ); }else if(key.isReadable()){ //如果key的注册事件为读取事件时执行 //返回为其创建此密钥(key)的通道 SocketChannel socketChannel = (SocketChannel) key.channel(); //解析读取该通道上的数据并返回打印 String data = readDataFromSocketChannel(socketChannel); System.out.println("return data:"+data); //关闭该套接字通道 socketChannel.close(); } //没有其他注册事件则移除该key键 keyIterator.remove(); } } } private static String readDataFromSocketChannel(SocketChannel socketChannel) throws IOException { StringBuilder data=new StringBuilder(); //分配一个新的字节缓冲区,新缓冲区的位置将为零,它的限制将是它的容量,即1024(B),如果容量为负整数则抛出IllegalArgumentException ByteBuffer byteBuffer = ByteBuffer.allocate(1024); while(true){ //循环读取数据 //清空缓冲区 //byteBuffer.clear(); //将Socket通道中数据读入字节缓冲区中 int read = socketChannel.read(byteBuffer); if(read == -1){ //缓冲区不存在数据时停止循环 break; } //翻转这个缓冲区.限制设置为当前位置 byteBuffer.flip(); //返回此缓冲区的限制 int limit = byteBuffer.limit(); //设置字符数组,存储读取的数据 char[] dst=new char[limit]; for (int i = 0; i < limit; i++) { //获取读取的数据 dst[i]= (char) byteBuffer.get(i); } //存入StringBuilder对象中 data.append(dst); //byteBuffer.clear(); } return data.toString(); }}
//Socket客户端public class NIOClient03 { public static void main(String[] args) throws IOException { //根据IP地址与端口与Socket服务器建立连接 Socket socket=new Socket("127.0.0.1",8888); //获取socket中输出流并写入 OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello world".getBytes()); //关闭输出流 outputStream.close(); }}
执行结果: