目标

- 实现返回当前服务器时间的功能- 采用半双工模式(主要是因为采用telnet为客户端,然后telnet默认情况下是半双工)- 客户端连接后,可以发送 time,stop命令. 只有客户端发送stop命令后,服务段才主动断开链路。- 不考虑读半包和写半包的情况

代码和注释

废话不多说,尽在代码中。直接拷贝即可运行(jdk7或以上)

package com.aio;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousServerSocketChannel;import java.nio.channels.AsynchronousSocketChannel;import java.nio.channels.CompletionHandler;import java.util.Date;import java.util.concurrent.CountDownLatch;/** * Author :  Rocky * Date : 21/12/2016 15:17 * De ion : * Test : */public class TimeServer {    public static void main(String[] args) throws InterruptedException {        AsynchronousServerSocketChannel assc = null;        try {            assc = AsynchronousServerSocketChannel.open();            assc.bind(new InetSocketAddress(8888));        } catch (IOException e) {            e.printStackTrace();            System.exit(1);        }        doAccept(assc);        CountDownLatch latch = new CountDownLatch(1);        latch.await();    }    private static void doAccept(AsynchronousServerSocketChannel assc) {        assc.accept(assc, new AcceptCompletionHandle());    }    private static class AcceptCompletionHandle implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> {        @Override        public void completed(AsynchronousSocketChannel result, AsynchronousServerSocketChannel assc) {            //继续监听accept事件            assc.accept(assc, this);            //开始监听可读时间            ByteBuffer readBuf = ByteBuffer.allocate(1024);            result.read(readBuf, readBuf, new ReadCompletionHandler(result));        }        @Override        public void failed(Throwable exc, AsynchronousServerSocketChannel assc) {            System.out.println("accept异常,继续accept");            assc.accept(assc, this);        }    }    private static class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {        private AsynchronousSocketChannel asc;        public ReadCompletionHandler(AsynchronousSocketChannel asc) {            this.asc = asc;        }        @Override        public void completed(Integer result, ByteBuffer readedData) {            //如果对端链路关闭            if (result < 0) {                try {                    asc.close();                } catch (IOException e) {                    e.printStackTrace();                }                return;            }            //如果读取到对端发送过来的数据            if (result > 0) {                readedData.flip();                byte[] data = new byte[readedData.remaining()];                readedData.get(data);                String command = null;                try {                    command = new String(data, "UTF-8");                    if ("time
".equalsIgnoreCase(command)) {                        doWrite(new Date().toString() + "
");                    } else if ("stop
".equalsIgnoreCase(command)) {                        doWriteAndClose("bye.
");                    } else if ("
".equalsIgnoreCase(command)) {                        doWrite("
");                    } else {                        doWrite("unknown command
");                    }                } catch (UnsupportedEncodingException e) {                    e.printStackTrace();                    doWrite("server error
");                }            }            //如果未读取到数据            else {                //继续尝试读取对端发送的数据                ByteBuffer readBuf = ByteBuffer.allocate(1024);                asc.read(readBuf, readBuf, this);            }        }        private void doWriteAndClose(String response) {            ByteBuffer repBuf = null;            try {                repBuf = ByteBuffer.wrap(response.getBytes("UTF-8"));            } catch (UnsupportedEncodingException e) {                e.printStackTrace();            }            if (repBuf != null) {                asc.write(repBuf, repBuf, new CompletionHandler<Integer, ByteBuffer>() {                    @Override                    public void completed(Integer result, ByteBuffer repBuf) {                        if (repBuf.hasRemaining()) {                            asc.write(repBuf, repBuf, this);                        }                        //写完成后,关闭链路                        else {                            try {                                asc.close();                            } catch (IOException e) {                                e.printStackTrace();                            }                        }                    }                    @Override                    public void failed(Throwable exc, ByteBuffer repBuf) {                        exc.printStackTrace();                        try {                            asc.close();                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                });            }        }        private void doWrite(String response) {            ByteBuffer repBuf = null;            try {                repBuf = ByteBuffer.wrap(response.getBytes("UTF-8"));            } catch (UnsupportedEncodingException e) {                e.printStackTrace();            }            if (repBuf != null) {                asc.write(repBuf, repBuf, new WriteCompletionHandler(asc, this));            }        }        @Override        public void failed(Throwable exc, ByteBuffer readedData) {            exc.printStackTrace();            try {                asc.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }    private static class WriteCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {        private AsynchronousSocketChannel asc;        private ReadCompletionHandler rch;        public WriteCompletionHandler(AsynchronousSocketChannel asc, ReadCompletionHandler rch) {            this.asc = asc;            this.rch = rch;        }        @Override        public void completed(Integer result, ByteBuffer repBuf) {            if (repBuf.hasRemaining()) {                asc.write(repBuf, repBuf, this);            }            //写完成后(对端读取完成),再尝试读(半双工模式)            else {                //继续尝试读取对端发送的数据                ByteBuffer readBuf = ByteBuffer.allocate(1024);                asc.read(readBuf, readBuf, rch);            }        }        @Override        public void failed(Throwable exc, ByteBuffer repBuf) {            exc.printStackTrace();            try {                asc.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

测试

telnet 127.0.0.1 8888Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.timeWed Dec 21 17:05:44 CST 2016timeWed Dec 21 17:07:44 CST 2016sunknown commandfunknown commandstopbye.Connection closed by foreign host.
收藏 打印