一个简单的echo服务器,客户端向服务端发送消息,服务端进行响应,当客户端发送quit字符串时,断开客户端和服务端的连接。使用NIO实现
public class EchoServer_NIO { private Selector selector; private ByteBuffer sendBuf = ByteBuffer.allocate(1024); private ByteBuffer recBuf = ByteBuffer.allocate(1024); public EchoServer_NIO(){ try { System.out.println("服务器正在启动"); selector = Selector.open(); ServerSocketChannel ssc = ServerSocketChannel.open(); //设置非阻塞模式 ssc.configureBlocking(false); //绑定端口 ssc.bind(new InetSocketAddress(8777)); ssc.register(selector, SelectionKey.OP_ACCEPT); System.out.println("服务器启动成功"); } catch (Exception e) { e.printStackTrace(); System.out.println("服务器启动失败"); } } public static void main(String[] args) { new EchoServer_NIO().service(); } public void service(){ while (true){ try { int select = selector.select(); if (select>0){ Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); iterator.remove(); //如果是有效的 if (key.isValid()){ if (key.isAcceptable()){ accept(key); }else if(key.isReadable()){ read(key); }else if(key.isWritable()){ write(key); } } } selectionKeys.clear(); } } catch (Exception e) { e.printStackTrace(); } } } private void accept(SelectionKey key){ try { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector,SelectionKey.OP_READ); }catch (Exception e){ e.printStackTrace(); } } private void read(SelectionKey key) { try { recBuf.clear(); SocketChannel sc = (SocketChannel) key.channel(); int read = sc.read(recBuf); if (read<0){ key.channel().close(); key.cancel(); return; } recBuf.flip(); String recText = new String(recBuf.array(),0,read); System.out.println(recText); if (recText.equals("quit")){ sendBuf.clear(); sendBuf.put("bye".getBytes()); sc.write(sendBuf); key.channel().close(); key.cancel(); return; } sc.register(selector,SelectionKey.OP_WRITE); }catch (Exception e){ e.printStackTrace(); } } private void write(SelectionKey key) { try { SocketChannel sc = (SocketChannel) key.channel(); sendBuf.clear(); String sendText = "hello"; sendBuf.put(sendText.getBytes()); sendBuf.flip(); sc.write(sendBuf); sc.register(selector,SelectionKey.OP_READ); }catch (Exception e){ e.printStackTrace(); } } }
public class EchoClient_NIO { private Selector selector; private ByteBuffer sendBuf = ByteBuffer.allocate(1024); private ByteBuffer revBuf = ByteBuffer.allocate(1024); public EchoClient_NIO(){ try { System.out.println("正在连接服务器..."); SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_CONNECT); socketChannel.connect(new InetSocketAddress("localhost",8777)); }catch (Exception e){ e.printStackTrace(); } } public void service() throws IOException { while (true){ selector.select(); Set<SelectionKey> keys = selector.selectedKeys(); Iterator<SelectionKey> iterator = keys.iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); iterator.remove(); if (key.isConnectable()){ connect(key); }else if (key.isReadable()){ read(key); }else if (key.isWritable()){ write(key); } keys.clear(); } } } private void connect(SelectionKey key) { try { SocketChannel sc = (SocketChannel) key.channel(); if (sc.isConnectionPending()){ sc.finishConnect(); System.out.println("服务器连接成功"); sc.register(selector,SelectionKey.OP_WRITE); } } catch (IOException e) { e.printStackTrace(); System.out.println("服务器连接失败"); } } private void read(SelectionKey key) { try { revBuf.clear(); SocketChannel sc = (SocketChannel) key.channel(); int read = sc.read(revBuf); if (read>0) { revBuf.flip(); String recText = new String(revBuf.array(), 0, read); System.out.println(recText); if (recText.equals("quit")) { key.channel().close(); key.cancel(); return; } sc.register(selector, SelectionKey.OP_WRITE); } }catch (Exception e){ e.printStackTrace(); } } private void write(SelectionKey key) { try { sendBuf.clear(); SocketChannel sc = (SocketChannel) key.channel(); Scanner scanner = new Scanner(System.in); String message = scanner.nextLine(); sendBuf.put(message.getBytes()); sendBuf.flip(); sc.write(sendBuf); if (message.equals("quit")){ key.channel().close(); key.cancel(); selector.close(); return; } sc.register(selector,SelectionKey.OP_READ); }catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args) throws IOException { new EchoClient_NIO().service(); } }
文章来源: 使用NIO实现一个echo服务器