NioServer.java
package io.torey.niotest;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set;/** * NIO服务器端 */public class NioServer { public static void main(String[] args){ NioServer nioServer = new NioServer(); try { nioServer.start(); } catch (IOException e) { e.printStackTrace(); } } /** * 启动 */ public void start() throws IOException{ //1 创建Selector //2 通过ServerSocketChannel创建channel通道 //3 为channel通道绑定监听端口 //4 重点:设置channel为非阻塞模式 //5 将channel注册到selector上,监听连接事件 //6 循环等待新接入的连接 //7 根据就绪状态,调用对应方法处理业务逻辑 //1 创建Selector Selector selector = Selector.open(); //2 通过ServerSocketChannel创建channel通道 ServerSocketChannel serverSocketChannel= ServerSocketChannel.open(); //3 为channel通道绑定监听端口 serverSocketChannel.bind(new InetSocketAddress(8000)); //4 重点:设置channel为非阻塞模式 serverSocketChannel.configureBlocking(false); //5 将channel注册到selector上,监听连接事件 serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT); System.out.println("服务器启动成功!!"); //6 循环等待新接入的连接 while (true) { //这个方法是阻塞方法,获取可用的channel数量 int readyChannels= selector.select(); if (readyChannels==0) { continue; } //获取可用channel的集合 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //selectionKey的实例 SelectionKey selectionKey = iterator.next(); //移除Set中当前的selectionKey,重点 iterator.remove(); //7 根据就绪状态,调用对应方法处理业务逻辑 //如果是 接入事件 if (selectionKey.isAcceptable()) { acceptHandler(serverSocketChannel,selector); } //如果是 可读事件 if (selectionKey.isReadable()) { readHandler(selectionKey,selector); } } } } /** * 接入事件处理器 * @param serverSocketChannel * @param selector * @throws IOException */ private void acceptHandler(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException{ //如果要是接入事件,创建socketChannel //将socketChannel设置为非阻塞工作模式 //将channel注册到selector上,监听 可读事件 //回复客户端提示信息 System.out.println("有一个客户端进来了..."); //如果要是接入事件,创建socketChannel SocketChannel socketChannel = serverSocketChannel.accept(); //将socketChannel设置为非阻塞工作模式 socketChannel.configureBlocking(false); //将channel注册到selector上,监听 可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //回复客户端提示信息 socketChannel.write(Charset.forName("UTF-8") .encode("你与聊天室里其他人都不是朋友关系,请注意隐私安全!!")); } /** * 可读事件处理器 */ private void readHandler(SelectionKey selectionKey,Selector selector) throws IOException{ //要从selectionKey中获取到已经就绪的channel //创建buffer //循环读取客户端请求信息 //将channel再次注册到selector上,监听他的可读事件 //将客户端发送的请求信息,广播给其他客户端 //要从selectionKey中获取到已经就绪的channel SocketChannel socketChannel= (SocketChannel)selectionKey.channel(); //创建buffer ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //循环读取客户端请求信息 StringBuilder reques=new StringBuilder(); while (socketChannel.read(byteBuffer) > 0) { //切换buffer为读模式 byteBuffer.flip(); //读取buffer中的内容 reques.append(Charset.forName("UTF-8").decode(byteBuffer)); } //将channel再次注册到selector上,监听他的可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //将客户端发送的请求信息,广播给其他客户端 if (reques.length()>0) { System.out.println("收到客户端消息:"+reques.toString()); } }}package io.torey.niotest;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set;/** * NIO服务器端 */public class NioServer { public static void main(String[] args){ NioServer nioServer = new NioServer(); try { nioServer.start(); } catch (IOException e) { e.printStackTrace(); } } /** * 启动 */ public void start() throws IOException{ //1 创建Selector //2 通过ServerSocketChannel创建channel通道 //3 为channel通道绑定监听端口 //4 重点:设置channel为非阻塞模式 //5 将channel注册到selector上,监听连接事件 //6 循环等待新接入的连接 //7 根据就绪状态,调用对应方法处理业务逻辑 //1 创建Selector Selector selector = Selector.open(); //2 通过ServerSocketChannel创建channel通道 ServerSocketChannel serverSocketChannel= ServerSocketChannel.open(); //3 为channel通道绑定监听端口 serverSocketChannel.bind(new InetSocketAddress(8000)); //4 重点:设置channel为非阻塞模式 serverSocketChannel.configureBlocking(false); //5 将channel注册到selector上,监听连接事件 serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT); System.out.println("服务器启动成功!!"); //6 循环等待新接入的连接 while (true) { //这个方法是阻塞方法,获取可用的channel数量 int readyChannels= selector.select(); if (readyChannels==0) { continue; } //获取可用channel的集合 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //selectionKey的实例 SelectionKey selectionKey = iterator.next(); //移除Set中当前的selectionKey,重点 iterator.remove(); //7 根据就绪状态,调用对应方法处理业务逻辑 //如果是 接入事件 if (selectionKey.isAcceptable()) { acceptHandler(serverSocketChannel,selector); } //如果是 可读事件 if (selectionKey.isReadable()) { readHandler(selectionKey,selector); } } } } /** * 接入事件处理器 * @param serverSocketChannel * @param selector * @throws IOException */ private void acceptHandler(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException{ //如果要是接入事件,创建socketChannel //将socketChannel设置为非阻塞工作模式 //将channel注册到selector上,监听 可读事件 //回复客户端提示信息 System.out.println("有一个客户端进来了..."); //如果要是接入事件,创建socketChannel SocketChannel socketChannel = serverSocketChannel.accept(); //将socketChannel设置为非阻塞工作模式 socketChannel.configureBlocking(false); //将channel注册到selector上,监听 可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //回复客户端提示信息 socketChannel.write(Charset.forName("UTF-8") .encode("你与聊天室里其他人都不是朋友关系,请注意隐私安全!!")); } /** * 可读事件处理器 */ private void readHandler(SelectionKey selectionKey,Selector selector) throws IOException{ //要从selectionKey中获取到已经就绪的channel //创建buffer //循环读取客户端请求信息 //将channel再次注册到selector上,监听他的可读事件 //将客户端发送的请求信息,广播给其他客户端 //要从selectionKey中获取到已经就绪的channel SocketChannel socketChannel= (SocketChannel)selectionKey.channel(); //创建buffer ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //循环读取客户端请求信息 StringBuilder reques=new StringBuilder(); while (socketChannel.read(byteBuffer) > 0) { //切换buffer为读模式 byteBuffer.flip(); //读取buffer中的内容 reques.append(Charset.forName("UTF-8").decode(byteBuffer)); } //将channel再次注册到selector上,监听他的可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //将客户端发送的请求信息,广播给其他客户端 if (reques.length()>0) { System.out.println("收到客户端消息:"+reques.toString()); } }}
NioClientHandler.java
package io.torey.niotest;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.nio.charset.Charset;import java.util.Iterator;import java.util.Set;/** * 服务器端线程类,专门接收服务器端响应 */public class NioClientHandler implements Runnable { private Selector selector; public NioClientHandler(Selector selector) { this.selector = selector; } @Override public void run() { try{ while (true) { //这个方法是阻塞方法,获取可用的channel数量 int readyChannels= selector.select(); if (readyChannels==0) { continue; } //获取可用channel的集合 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //selectionKey的实例 SelectionKey selectionKey = iterator.next(); //移除Set中当前的selectionKey,重点 iterator.remove(); //7 根据就绪状态,调用对应方法处理业务逻辑 //如果是 可读事件 if (selectionKey.isReadable()) { readHandler(selectionKey,selector); } } }}catch (Exception ex){ ex.printStackTrace(); } } /** * 可读事件处理器 */ private void readHandler(SelectionKey selectionKey,Selector selector) throws IOException { //要从selectionKey中获取到已经就绪的channel //创建buffer //循环读取服务器端请求信息 //将channel再次注册到selector上,监听他的可读事件 //将服务器端发送的请求信息,广播给其他服务器端 //要从selectionKey中获取到已经就绪的channel SocketChannel socketChannel= (SocketChannel)selectionKey.channel(); //创建buffer ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //循环读取服务器端请求信息 StringBuilder response=new StringBuilder(); while (socketChannel.read(byteBuffer) > 0) { //切换buffer为读模式 byteBuffer.flip(); //读取buffer中的内容 response.append(Charset.forName("UTF-8").decode(byteBuffer)); } //将channel再次注册到selector上,监听他的可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //将服务器端发送的请求信息,打印到本地 if (response.length()>0) { System.out.println("收到服务器端消息:"+response.toString()); } }}
NioServer.java
package io.torey.niotest;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.nio.charset.Charset;import java.util.Iterator;import java.util.Set;/** * NIO服务器端 */public class NioServer { public static void main(String[] args){ NioServer nioServer = new NioServer(); try { nioServer.start(); } catch (IOException e) { e.printStackTrace(); } } /** * 启动 */ public void start() throws IOException{ //1 创建Selector //2 通过ServerSocketChannel创建channel通道 //3 为channel通道绑定监听端口 //4 重点:设置channel为非阻塞模式 //5 将channel注册到selector上,监听连接事件 //6 循环等待新接入的连接 //7 根据就绪状态,调用对应方法处理业务逻辑 //1 创建Selector Selector selector = Selector.open(); //2 通过ServerSocketChannel创建channel通道 ServerSocketChannel serverSocketChannel= ServerSocketChannel.open(); //3 为channel通道绑定监听端口 serverSocketChannel.bind(new InetSocketAddress(8000)); //4 重点:设置channel为非阻塞模式 serverSocketChannel.configureBlocking(false); //5 将channel注册到selector上,监听连接事件 serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT); System.out.println("服务器启动成功!!"); //6 循环等待新接入的连接 while (true) { //这个方法是阻塞方法,获取可用的channel数量 int readyChannels= selector.select(); if (readyChannels==0) { continue; } //获取可用channel的集合 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //selectionKey的实例 SelectionKey selectionKey = iterator.next(); //移除Set中当前的selectionKey,重点 iterator.remove(); //7 根据就绪状态,调用对应方法处理业务逻辑 //如果是 接入事件 if (selectionKey.isAcceptable()) { acceptHandler(serverSocketChannel,selector); } //如果是 可读事件 if (selectionKey.isReadable()) { readHandler(selectionKey,selector); } } } } /** * 接入事件处理器 * @param serverSocketChannel * @param selector * @throws IOException */ private void acceptHandler(ServerSocketChannel serverSocketChannel,Selector selector) throws IOException{ //如果要是接入事件,创建socketChannel //将socketChannel设置为非阻塞工作模式 //将channel注册到selector上,监听 可读事件 //回复客户端提示信息 System.out.println("有一个客户端进来了..."); //如果要是接入事件,创建socketChannel SocketChannel socketChannel = serverSocketChannel.accept(); //将socketChannel设置为非阻塞工作模式 socketChannel.configureBlocking(false); //将channel注册到selector上,监听 可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //回复客户端提示信息 socketChannel.write(Charset.forName("UTF-8") .encode("你与聊天室里其他人都不是朋友关系,请注意隐私安全!!")); } /** * 可读事件处理器 */ private void readHandler(SelectionKey selectionKey,Selector selector) throws IOException{ //要从selectionKey中获取到已经就绪的channel //创建buffer //循环读取客户端请求信息 //将channel再次注册到selector上,监听他的可读事件 //将客户端发送的请求信息,广播给其他客户端 //要从selectionKey中获取到已经就绪的channel SocketChannel socketChannel= (SocketChannel)selectionKey.channel(); //创建buffer ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //循环读取客户端请求信息 StringBuilder reques=new StringBuilder(); while (socketChannel.read(byteBuffer) > 0) { //切换buffer为读模式 byteBuffer.flip(); //读取buffer中的内容 reques.append(Charset.forName("UTF-8").decode(byteBuffer)); } //将channel再次注册到selector上,监听他的可读事件 socketChannel.register(selector,SelectionKey.OP_READ); //将客户端发送的请求信息,广播给其他客户端 if (reques.length()>0) { System.out.println("收到客户端消息:"+reques.toString()); } }}
测试截图
- 先开启 服务器端
- 在开启 客户端

