设为首页 加入收藏

TOP

2.1.2 同步阻塞式I/O创建的TimeServer源码分析
2014-07-09 12:30:42 来源: 作者: 【 】 浏览:91
Tags:2.1.2 同步 阻塞 I/O 创建 TimeServer 源码 分析

2.1.2  同步阻塞式I/O创建的TimeServer源码分析

代码清单2-1  同步阻塞I/O的TimeServer

(备注:以下代码行号均对应源代码中实际行号。)
 

  1. 1.  package com.phei.netty.bio;  
  2. 2.  import java.io.IOException;  
  3. 3.  import java.net.ServerSocket;  
  4. 4.  import java.net.Socket;  
  5. 5.  /**  
  6. 6.   * @author lilinfeng  
  7. 7.   * @date 2014年2月14日  
  8. 8.   * @version 1.0  
  9. 9.   */  
  10. 10. public class TimeServer {  
  11. 11.   
  12. 12.     /**  
  13. 13.      * @param args  
  14. 14.      * @throws IOException  
  15. 15.      */  
  16. 16.     public static void main(String[] args) throws IOException {  
  17. 17.     int port = 8080;  
  18. 18.     if (args != null && args.length > 0) {  
  19. 19.   
  20. 20.         try {  
  21. 21.         port = Integer.valueOf(args[0]);  
  22. 22.         } catch (NumberFormatException e) {  
  23. 23.         // 采用默认值  
  24. 24.         }  
  25. 25.   
  26. 26.     }  
  27. 27.     ServerSocket server = null;  
  28. 28.     try {  
  29. 29.         server = new ServerSocket(port);  
  30. 30.         System.out.println("The time server is start in port : " + port);  
  31. 31.         Socket socket = null;  
  32. 32.         while (true) {  
  33. 33.         socket = server.accept();  
  34. 34.         new Thread(new TimeServerHandler(socket)).start();  
  35. 35.         }  
  36. 36.     } finally {  
  37. 37.         if (server != null) {  
  38. 38.         System.out.println("The time server close");  
  39. 39.         server.close();  
  40. 40.         server = null;  
  41. 41.         }  
  42. 42.     }  
  43. 43.     }  
  44. 44. } 

TimeServer根据传入的参数设置监听端口,如果没有入参,使用默认值8080,29行通过构造函数创建ServerSocket,如果端口合法且没有被占用,服务端监听成功。32~35行通过一个无限循环来监听客户端的连接,如果没有客户端接入,则主线程阻塞在ServerSocket的accept操作上。启动TimeServer,通过JvisualVM打印线程堆栈,我们可以发现主程序确实阻塞在accept操作上,如图2-2所示。

当有新的客户端接入的时候,执行代码34行,以Socket为参数构造TimeServerHandler对象,TimeServerHandler是一个Runnable,使用它为构造函数的参数创建一个新的客户端线程处理这条Socket链路。下面我们继续分析TimeServerHandler的代码。

代码清单2-2  同步阻塞I/O的TimeServerHandler
 

  1. 13. public class TimeServerHandler implements Runnable {  
  2. 14.   
  3. 15.     private Socket socket;  
  4. 16.   
  5. 17.     public TimeServerHandler(Socket socket) {  
  6. 18.     this.socket = socket;  
  7. 19.     }  
  8. 20.   
  9. 21.     /*  
  10. 22.      * (non-Javadoc)  
  11. 23.      *   
  12. 24.      * @see java.lang.Runnable#run()  
  13. 25.      */  
  14. 26.     @Override  
  15. 27.     public void run() {  
  16. 28.     BufferedReader in = null;  
  17. 29.     PrintWriter out = null;  
  18. 30.     try {  
  19. 31.         in = new BufferedReader(new InputStreamReader(  
  20. 32.             this.socket.getInputStream()));  
  21. 33.         out = new PrintWriter(this.socket.getOutputStream(), true);  
  22. 34.         String currentTime = null;  
  23. 35.         String body = null;  
  24. 36.         while (true) {  
  25. 37.         body = in.readLine();  
  26. 38.         if (body == null)  
  27. 39.             break;  
  28. 40.         System.out.println("The time server receive order : " + body);  
  29. 41.         currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)   new java.util.Date(  
  30. 42.             System.currentTimeMillis()).toString() : "BAD ORDER";  
  31. 43.         out.println(currentTime);  
  32. 44.         }  
  33. 45.   
  34. 46.     } catch (Exception e) {  
  35. 47.         if (in != null) {  
  36. 48.         try {  
  37. 49.             in.close();  
  38. 50.         } catch (IOException e1) {  
  39. 51.             e1.printStackTrace();  
  40. 52.         }  
  41. 53.         }  
  42. 54.         if (out != null) {  
  43. 55.         out.close();  
  44. 56.         out = null;  
  45. 57.         }  
  46. 58.         if (this.socket != null) {  
  47. 59.         try {  
  48. 60.             this.socket.close();  
  49. 61.         } catch (IOException e1) {  
  50. 62.             e1.printStackTrace();  
  51. 63.         }  
  52. 64.         this.socket = null;  
  53. 65.         }  
  54. 66.     }  
  55. 67.     }  
  56. 68. } 

37行通过BufferedReader读取一行,如果已经读到了输入流的尾部,则返回值为null,退出循环。如果读到了非空值,则对内容进行判断,如果请求消息为查询时间的指令"QUERY TIME ORDER"则获取当前最新的系统时间,通过PrintWriter的println函数发送给客户端,最后退出循环。代码47~64行释放输入流、输出流、和Socket套接字句柄资源,最后线程自动销毁并被虚拟机回收。

在下一个小结,我们将介绍同步阻塞I/O的客户端代码,然后分别运行服务端和客户端,查看下程序的运行结果。
 

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

51CTO读书频道二维码


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

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇2.1.1 BIO通信模型图 下一篇2.1.3 同步阻塞式I/O创建的TimeCl..

评论

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

·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)