1. public class NIOTimeClient {
    2. //本地默认端口号
    3. private static final int LOCAL_PORT = 3738;
    4. //服务端默认端口号
    5. private static final int REMOTE_PORT = 8585;
    6. public static void main(String[] args) {
    7. new Thread(new TimeClientHandler("127.0.0.1", REMOTE_PORT)).start();
    8. }
    9. private static class TimeClientHandler implements Runnable {
    10. private String host;
    11. private int port;
    12. private Selector selector;
    13. private SocketChannel socketChannel;
    14. private volatile boolean stop = false;
    15. public TimeClientHandler(String host, int port) {
    16. this.host = host;
    17. this.port = port;
    18. try {
    19. selector = Selector.open();
    20. socketChannel = SocketChannel.open();
    21. //从本地3738端口连接
    22. socketChannel.bind(new InetSocketAddress(LOCAL_PORT));
    23. socketChannel.configureBlocking(false);
    24. System.out.println("TimeClient started at port " + LOCAL_PORT);
    25. } catch (IOException e) {
    26. e.printStackTrace();
    27. }
    28. }
    29. @Override
    30. public void run() {
    31. try {
    32. doConnect();
    33. } catch (IOException e) {
    34. e.printStackTrace();
    35. System.exit(1);
    36. }
    37. while (!stop) {
    38. try {
    39. //选择就绪通道
    40. selector.select(1000);
    41. Set<SelectionKey> selectionKeys = selector.selectedKeys();
    42. Iterator<SelectionKey> it = selectionKeys.iterator();
    43. SelectionKey selectionKey;
    44. while (it.hasNext()) {
    45. selectionKey = it.next();
    46. it.remove();
    47. try {
    48. handleInput(selectionKey);
    49. } catch (Exception e) {
    50. if (null != selectionKey) {
    51. selectionKey.cancel();
    52. if (null != selectionKey.channel()) {
    53. selectionKey.channel().close();
    54. }
    55. }
    56. }
    57. }
    58. } catch (IOException e) {
    59. e.printStackTrace();
    60. }
    61. }
    62. //停止 关闭selector
    63. if(null != selector){
    64. try {
    65. System.out.println("关闭selector");
    66. //selector关闭之后 注册在其上面的channel都会关闭
    67. selector.close();
    68. } catch (IOException e) {
    69. e.printStackTrace();
    70. }
    71. }
    72. }
    1. /**
    2. * 处理输入
    3. */
    4. private void handleInput(SelectionKey selectionKey) throws IOException {
    5. if(selectionKey.isValid()){
    6. //获取key对应的channel
    7. SocketChannel channel = (SocketChannel) selectionKey.channel();
    8. //首先判断connection
    9. if(selectionKey.isConnectable()){
    10. if(channel.finishConnect()){
    11. channel.register(selector,SelectionKey.OP_READ);
    12. doWrite(channel);
    13. }else {
    14. System.exit(1);
    15. }
    16. }
    17. //判断是否可读
    18. if(selectionKey.isReadable()){
    19. ByteBuffer buffer = ByteBuffer.allocate(1025-1);
    20. int read = channel.read(buffer);
    21. if(read>0){
    22. //回绕缓冲区 方便读取
    23. buffer.flip();
    24. byte[] elements = new byte[buffer.remaining()];
    25. buffer.get(elements);
    26. String content = new String(elements,StandardCharsets.UTF_8);
    27. System.out.println("The time client received time : " + content);
    28. stop = true;
    29. }else if(read < 0){
    30. selectionKey.cancel();
    31. channel.close();
    32. }else {
    33. //读到0字节 忽略
    34. }
    35. }
    36. }
    37. }
    38. private void doConnect() throws IOException {
    39. //如果直接连接成功 就将其注册到selector并监听读取就绪事件
    40. if (socketChannel.connect(new InetSocketAddress(host, port))) {
    41. socketChannel.register(selector, SelectionKey.OP_READ);
    42. doWrite(socketChannel);
    43. } else {
    44. //没有连接成功 就注册 注意这里是OP_CONNECT
    45. socketChannel.register(selector, SelectionKey.OP_CONNECT);
    46. }
    47. }
    48. private void doWrite(SocketChannel socketChannel) throws IOException {
    49. byte[] request = "QUERY TIME ORDER ".getBytes(StandardCharsets.UTF_8);
    50. ByteBuffer byteBuffer = ByteBuffer.allocate(request.length);
    51. byteBuffer.put(request);
    52. byteBuffer.flip();
    53. socketChannel.write(byteBuffer);
    54. if (!byteBuffer.hasRemaining()) {
    55. System.out.println("Send order to server successfully.");
    56. }
    57. }
    58. }
    59. }