设为首页 加入收藏

TOP

2.3.3 NIO创建的TimeServer源码分析(1)
2014-07-09 12:30:25 来源: 作者: 【 】 浏览:108
Tags:2.3.3 NIO 创建 TimeServer 源码 分析

2.3.3  NIO创建的TimeServer源码分析(1)

我们将在TimeServer例程中给出完整的NIO创建的时间服务器源码。

代码清单2-8  NIO时间服务器 TimeServer

  1. 9.  public class TimeServer {  
  2. 10.   
  3. 11.     /**  
  4. 12.      * @param args  
  5. 13.      * @throws IOException  
  6. 14.      */  
  7. 15.     public static void main(String[] args) throws IOException {  
  8. 16.     int port = 8080;  
  9. 17.     if (args != null && args.length > 0) {  
  10. 18.         try {  
  11. 19.         port = Integer.valueOf(args[0]);  
  12. 20.         } catch (NumberFormatException e) {  
  13. 21.         // 采用默认值  
  14. 22.         }  
  15. 23.     }  
  16. 24.     MultiplexerTimeServer timeServer = new MultiplexerTimeServer (port);  
  17. 25.     New Thread(timeServer, "NIO-MultiplexerTimeServer-001").start();  
  18. 26.     }  
  19. 27. } 

我们对NIO创建的TimeServer进行简单分析下,16~23行跟之前的一样,设置监听端口。24~25行创建了一个被称为MultiplexerTimeServer的多路复用类,它是个一个独立的线程,负责轮询多路复用器Selctor,可以处理多个客户端的并发接入。现在我们继续看MultiplexerTimeServer的源码。

代码清单2-8  NIO时间服务器  MultiplexerTimeServer

  1. 17. public class MultiplexerTimeServer implements Runnable {  
  2. 18.   
  3. 19.     private Selector selector;  
  4. 20.   
  5. 21.     private ServerSocketChannel servChannel;  
  6. 22.   
  7. 23.     private volatile boolean stop;  
  8. 24.   
  9. 25.     /**  
  10. 26.      * 初始化多路复用器、绑定监听端口  
  11. 27.      *   
  12. 28.      * @param port  
  13. 29.      */  
  14. 30.     public MultiplexerTimeServer(int port) {  
  15. 31.     try {  
  16. 32.         selector = Selector.open();  
  17. 33.         servChannel = ServerSocketChannel.open();  
  18. 34.         servChannel.configureBlocking(false);  
  19. 35.         servChannel.socket().bind(new InetSocketAddress(port), 1024);  
  20. 36.         servChannel.register(selector, SelectionKey.OP_ACCEPT);  
  21. 37.         System.out.println("The time server is start in port : " + port);  
  22. 38.     } catch (IOException e) {  
  23. 39.         e.printStackTrace();  
  24. 40.         System.exit(1);  
  25. 41.     }  
  26. 42.     }  
  27. 43.   
  28. 44.     public void stop() {  
  29. 45.     this.stop = true;  
  30. 46.     }  
  31. 47.   
  32. 48.     /*  
  33. 49.      * (non-Javadoc)  
  34. 50.      *   
  35. 51.      * @see java.lang.Runnable#run()  
  36. 52.      */  
  37. 53.     @Override  
  38. 54.     public void run() {  
  39. 55.     while (!stop) {  
  40. 56.         try {  
  41. 57.         selector.select(1000);  
  42. 58.         Set<SelectionKey> selectedKeys = selector.selectedKeys();  
  43. 59.         Iterator<SelectionKey> it = selectedKeys.iterator();  
  44. 60.         SelectionKey key = null;  
  45. 61.         while (it.hasNext()) {  
  46. 62.             key = it.next();  
  47. 63.             it.remove();  
  48. 64.             try {  
  49. 65.             handleInput(key);  
  50. 66.             } catch (Exception e) {  
  51. 67.             if (key != null) {  
  52. 68.                 key.cancel();  
  53. 69.                 if (key.channel() != null)  
  54. 70.                 key.channel().close();  
  55. 71.             }  
  56. 72.             }  
  57. 73.         }  
  58. 74.         } catch (Throwable t) {  
  59. 75.         t.printStackTrace();  
  60. 76.         }  
  61. 77.     }  
  62. 78.   
  63. 79.     // 多路复用器关闭后,所有注册在上面的Channel和Pipe等资源都会被自动去注册并关闭,所以不需要重复释放资源  
  64. 80.     if (selector != null)  
  65. 81.         try {  
  66. 82.         selector.close();  
  67. 83.         } catch (IOException e) {  
  68. 84.         e.printStackTrace();  
  69. 85.         }  
  70. 86.     }  
  71. 87.   
  72. 88.     private void handleInput(SelectionKey key) throws IOException {  
  73. 89.   
  74. 90.     if (key.isValid()) {  
  75. 91.         // 处理新接入的请求消息  
  76. 92.         if (key.isAcceptable()) {  
  77. 93.         // Accept the new connection  
  78. 94.         ServerSocketChannel ssc = (ServerSocketChannel) key.channel();  
  79. 95.         SocketChannel sc = ssc.accept();  
  80. 96.         sc.configureBlocking(false);  
  81. 97.         // Add the new connection to the selector  
  82. 98.         sc.register(selector, SelectionKey.OP_READ);  
  83. 99.         }  
  84. 100.            if (key.isReadable()) {  
  85. 101.            // Read the data  
  86. 102.            SocketChannel sc = (SocketChannel) key.channel();  
  87. 103.            ByteBuffer readBuffer = ByteBuffer.allocate(1024);  
  88. 104.            int readBytes = sc.read(readBuffer);  
  89. 105.            if (readBytes > 0) {  
  90. 106.                readBuffer.flip();  
  91. 107.                byte[] bytes = new byte[readBuffer.remaining()];  
  92. 108.                readBuffer.get(bytes);  
  93. 109.                String body = new String(bytes, "UTF-8");  
  94. 110.                System.out.println("The time server receive order : "  
  95. 111.                    + body);  
  96. 112.                String currentTime = "QUERY TIME ORDER" 
  97. 113.                    .equalsIgnoreCase(body)   new java.util.Date(  
  98. 114.                    System.currentTimeMillis()).toString()  
  99. 115.                    : "BAD ORDER";  
  100. 116.                doWrite(sc, currentTime);  
  101. 117.            } else if (readBytes < 0) {  
  102. 118.                // 对端链路关闭  
  103. 119.                key.cancel();  
  104. 120.                sc.close();  
  105. 121.            } else  
  106. 122.                ; // 读到0字节,忽略  
  107. 123.            }  
  108. 124.        }  
  109. 125.        }  
  110. 126.      
  111. 127.        private void doWrite(SocketChannel channel, String response)  
  112. 128.            throws IOException {  
  113. 129.        if (response != null && response.trim().length() > 0) {  
  114. 130.            byte[] bytes = response.getBytes();  
  115. 131.            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);  
  116. 132.            writeBuffer.put(bytes);  
  117. 133.            writeBuffer.flip();  
  118. 134.            channel.write(writeBuffer);  
  119. 135.        }  
  120. 136.        }  
  121. 137.    } 

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:342347198

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇2.3.2 NIO服务端序列图 下一篇2.3.3 NIO创建的TimeServer源码分..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C语言指针从入门到基 (2025-12-26 05:21:36)
·【C语言指针初阶】C (2025-12-26 05:21:33)
·C语言指针的定义和使 (2025-12-26 05:21:31)
·在 Redis 中如何查看 (2025-12-26 03:19:03)
·Redis在实际应用中, (2025-12-26 03:19:01)