java NIO實現同步非阻塞伺服器
阿新 • • 發佈:2019-02-02
server
clientpackage net.smgui.util; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; 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; /** * Created by lutai on 2016/4/12. */ public class Server implements Runnable { private Selector selector; private ServerSocketChannel serverSocketChannel; private volatile boolean stop; public Server(int port) { try { selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); serverSocketChannel.bind(new InetSocketAddress(port), 1024); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("伺服器在"+port+"啟動"); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } public void stop() { this.stop = true; } public void run() { while (!stop) { try { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); SelectionKey key = null; while (iterator.hasNext()) { key = iterator.next(); iterator.remove(); try { handleInput(key); } catch (Exception e) { if (key != null) { key.cancel(); if (key.channel() != null) { key.channel().close(); } } } } } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } if (selector != null) { try { selector.close(); } catch (IOException e) { e.printStackTrace(); } } } private void handleInput(SelectionKey key) throws IOException { if (key.isValid()) { if (key.isAcceptable()) { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); SocketChannel sc = ssc.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); } else if (key.isReadable()) { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); int readBytes = sc.read(byteBuffer); if (readBytes > 0) { byteBuffer.flip(); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); System.out.println(new String(bytes, "UTF-8")); doWrite(sc); } else if (readBytes < 0) { key.cancel(); sc.close(); } else { } } } } private void doWrite(SocketChannel sc) throws IOException { byte[] bytes = "伺服器傳送訊息".getBytes(); ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length); byteBuffer.put(bytes); byteBuffer.flip(); sc.write(byteBuffer); } }
package net.smgui.util; 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; /** * Created by lutai on 2016/4/25. */ public class Client implements Runnable { private String host; private int port; private Selector selector; private SocketChannel socketChannel; private volatile boolean stop; public Client(String host, int port) { this.host = host; this.port = port; try { selector = Selector.open(); socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } public void run() { try { doConnect(); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } while (!stop) { try { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); SelectionKey key = null; while (iterator.hasNext()) { key = iterator.next(); iterator.remove(); try { handleInput(key); } catch (Exception e) { if (key != null) { key.cancel(); if (key.channel() != null) { key.channel().close(); } } } } } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } if (selector != null) { try { selector.close(); } catch (IOException e) { e.printStackTrace(); } } } private void handleInput(SelectionKey key) throws IOException { if (key.isValid()) { SocketChannel sc = (SocketChannel) key.channel(); if (key.isConnectable()) { if (sc.finishConnect()) { sc.register(selector, SelectionKey.OP_READ); doWrite(sc); } else { System.exit(-1); } } else if (key.isReadable()) { ByteBuffer byteBuffer = ByteBuffer.allocate(1024); int readBytes = sc.read(byteBuffer); if (readBytes > 0) { byteBuffer.flip(); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); System.out.println(new String(bytes, "UTF-8")); doWrite(sc); this.stop = true; } else if (readBytes < 0) { key.cancel(); sc.close(); } else { } } } } private void doConnect() throws IOException { if (socketChannel.connect(new InetSocketAddress(host, port))) { socketChannel.register(selector, SelectionKey.OP_READ); doWrite(socketChannel); } else { socketChannel.register(selector, SelectionKey.OP_CONNECT); } } private void doWrite(SocketChannel sc) throws IOException { byte[] bytes = "客戶端傳送訊息".getBytes(); ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length); byteBuffer.put(bytes); byteBuffer.flip(); sc.write(byteBuffer); if (!byteBuffer.hasRemaining()) { System.out.println("傳送資料成功"); } } }