JAVA之IO学习(二)NIO聊天室

    技术2022-07-12  77

    package main.java.com.founder.study.javaio.socket.nio; import java.io.Closeable; 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.Set; /** * Created by yan on 2020/6/30. */ public class NioChatServer { private static final int DEFAULT_PORT = 8888; private static final String QUIT = "quit"; private static final int BUFFER = 1024; private ServerSocketChannel server; private Selector selector; private ByteBuffer rBuffer = ByteBuffer.allocate(BUFFER); private ByteBuffer wBuffer = ByteBuffer.allocate(BUFFER); private Charset charset = Charset.forName("UTF-8"); private int port; public NioChatServer(int port){ this.port = port; } public NioChatServer(){ this(DEFAULT_PORT); } public void start(){ try { server = ServerSocketChannel.open(); server.configureBlocking(false); server.socket().bind(new InetSocketAddress(port)); selector = Selector.open(); //把serverSocketChannel的accept监听事件注册到selector上 server.register(selector, SelectionKey.OP_ACCEPT); System.out.println("启动服务器监听端口"+port); while(true){ //阻塞到至少有一个通道在你注册的事件上就绪了 //方法返回的int值表示有多少通道已经就绪,是自上次调用select()方法后有多少通道变成就绪状态 selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); for(SelectionKey key: selectionKeys){ //处理被触发的事件 handle(key); } //处理完事件清空 selectionKeys.clear(); } } catch (IOException e) { e.printStackTrace(); }finally { close(selector); } } private void handle(SelectionKey key) throws IOException { //Accept事件 和客户端建立了连接 if(key.isAcceptable()){ ServerSocketChannel server = (ServerSocketChannel)key.channel(); SocketChannel client = server.accept(); client.configureBlocking(false); client.register(selector,SelectionKey.OP_READ); System.out.println("客户端"+client.socket().getPort()+"建立连接"); } //read事件 客户端发送了消息 else if (key.isReadable()){ SocketChannel client = (SocketChannel)key.channel(); String fwdMsg = recive(client); if(fwdMsg.isEmpty()){ //客户端异常 key.cancel(); //让处在阻塞状态的select()方法立刻返回 //该方法使得选择器上的第一个还没有返回的选择操作立即返回 selector.wakeup(); }else{ //转发给其它人 forwardMessage(client,fwdMsg); //检查用户是否退出 if(readeyToQuit(fwdMsg)){ key.cancel(); selector.wakeup(); System.out.println("客户端"+client.socket().getPort()+"已经断开"); } } } } private void forwardMessage(SocketChannel client, String fwdMsg) throws IOException { for(SelectionKey key: selector.keys()){ if(key.channel() instanceof ServerSocketChannel){ continue; } if(key.isValid() && !client.equals(key.channel())){ wBuffer.clear(); wBuffer.put(charset.encode(fwdMsg)); wBuffer.flip(); while (wBuffer.hasRemaining()){ ((SocketChannel)key.channel()).write(wBuffer); } } } } private String recive(SocketChannel client) throws IOException { rBuffer.clear(); while (client.read(rBuffer) > 0); rBuffer.flip(); return String.valueOf(charset.decode(rBuffer)); } public boolean readeyToQuit(String msg){ return QUIT.equals(msg); } private static void close(Closeable closeable) { try { closeable.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { NioChatServer nioChatServer = new NioChatServer(7777); nioChatServer.start(); } } package main.java.com.founder.study.javaio.socket.nio; import java.io.Closeable; 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.SocketChannel; import java.nio.charset.Charset; import java.util.Set; /** * Created by yanon 2020/6/30. */ public class NioChatClient { final String QUIT = "quit" ; static final String DEFAULT_SERVER_HOST = "127.0.0.1"; static final int DEFAULT_PORT = 8888; private static final int BUFFER = 1024; private SocketChannel client; private Selector selector; private ByteBuffer rBuffer = ByteBuffer.allocate(BUFFER); private ByteBuffer wBuffer = ByteBuffer.allocate(BUFFER); private Charset charset = Charset.forName("UTF-8"); private String host; private int port; public NioChatClient(){ this(DEFAULT_SERVER_HOST,DEFAULT_PORT); } public NioChatClient(String host,int port){ this.host=host; this.port=port; } public void start(){ try { client = SocketChannel.open(); client.configureBlocking(false); selector = Selector.open(); client.register(selector, SelectionKey.OP_CONNECT); client.connect(new InetSocketAddress(host,port)); while(true){ selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); for(SelectionKey key: selectionKeys){ //处理被触发的事件 handle(key); } //处理完事件清空 selectionKeys.clear(); } } catch (IOException e) { e.printStackTrace(); } } private void handle(SelectionKey key) throws IOException { //connet事件 --连接就绪事件 if(key.isConnectable()){ SocketChannel client = (SocketChannel)key.channel(); if(client.isConnectionPending()){ client.finishConnect(); //处理用户的输入 new Thread(new UserInputHandler(this)).start(); } client.register(selector,SelectionKey.OP_READ); } //read事件--服务器转发消息 else if(key.isReadable()){ SocketChannel client = (SocketChannel)key.channel(); String msg = recive(client); if(msg.isEmpty()){ //服务器异常 close(selector); }else{ System.out.println(msg); } } } private String recive(SocketChannel client) throws IOException { rBuffer.clear(); while(client.read(rBuffer)>0); return String.valueOf(charset.decode(rBuffer)); } public void send(String msg) throws IOException { wBuffer.clear(); wBuffer.put(charset.encode(msg)); wBuffer.flip(); while(wBuffer.hasRemaining()){ client.write(wBuffer); } //检查用户是否退出 if(readeyToQuit(msg)){ close(selector); } } public boolean readeyToQuit(String msg){ return QUIT.equals(msg); } private static void close(Closeable closeable) { try { closeable.close(); } catch (IOException e) { e.printStackTrace(); } } } package main.java.com.founder.study.javaio.socket.nio; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * Created by yan on 2020/6/28. */ public class UserInputHandler implements Runnable{ final String QUIT = "quit" ; private NioChatClient chatClient; public UserInputHandler( NioChatClient chatClient ){ this.chatClient = chatClient ; } @Override public void run() { BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in)); while (true){ //先发给服务端 try { chatClient.send(consoleReader.readLine()); chatClient.readeyToQuit(consoleReader.readLine()); } catch (IOException e) { e.printStackTrace(); } } } }

     

    Processed: 0.012, SQL: 12