• java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型


    同步I/O模型的弊端
    ===>每一个线程的创建都会消耗服务端内存,当大量请求进来,会耗尽内存,导致服务宕机

    伪异步I/O的弊端分析
    ===>当对Socket的输入流进行读取操作的时候,它会一直阻塞下去,知道发生如下三件事情
    (1)有数据可读
    (2)可用数据已经读取完毕
    (3)发生空指针或者I/O异常
    ===>这意味着当对方发送请求或应答消息比较缓慢,或者网络传输比较慢时候,读取输入流的一方的通信线程将被长时间阻塞。在阻塞期间,其他接入的消息只能在消息队列中排队。
    ===>伪异步I/O实际上仅仅只是对之前I/O线程模型的一个简单优化,它无法从根本上解决同步I/O导致的通信线程阻塞问题,下面我们简单分析下如果通信对方返回应答时间过长,会引起的级联鼓掌。
    (1)服务端处理缓慢,返回应答消息耗费60s,平时只需要10ms
    (2)采用伪异步I/O线程正在读取故障服务节点的响应,由于读取输入流是阻塞的。因此,它将会被同步阻塞60s
    (3)假如所有的可用线程都被故障服务器阻塞,那后续所有的I/O消息都将在队列中排队。
    (4)由于线程池采用阻塞队列实现,当队列积满之后,后续入队列的操作将被阻塞
    (5)由于前端只有一个Accptor线程接收客户端接入,它被阻塞在线程池的同步阻塞队列之后,新的客户端请求消息将被拒绝,客户端会发生大量的连接超时。
    (6)由于几乎所有的链接都超时,调用者会认为系统崩溃,无法接收新的请求消息。

    【一】同步阻塞I/O服务端通信模型

    第一:socket同步阻塞服务器的启动

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.IOException;
     4 import java.net.ServerSocket;
     5 import java.net.Socket;
     6 
     7 /**
     8  * 时间服务器
     9  * 基于同步阻塞I/O实现的服务器模型
    10  * @author sxf
    11  *
    12  */
    13 public class TimerServer {
    14     
    15     /**
    16      * 启动timerServer服务器
    17      */
    18     public   void init(){
    19         int port=8000;
    20         //创建Socket服务
    21         ServerSocket server=null;
    22         try {
    23             server=new ServerSocket(port);
    24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
    25             Socket socket=null;
    26             while(true){
    27                 //获取一次socket请求
    28                 socket=server.accept();
    29                 //启动一个新线程处理socket请求
    30                 new Thread(new TimerServerHandler(socket)).start();
    31             }
    32         } catch (IOException e) {
    33             e.printStackTrace();
    34         }finally{
    35             if(server!=null){
    36                 try {
    37                     server.close();
    38                 } catch (IOException e) {
    39                     // TODO Auto-generated catch block
    40                     e.printStackTrace();
    41                 }
    42             }
    43             server=null;
    44         }
    45         
    46     }
    47 
    48     
    49     public static void main(String[] args) {
    50         //启动timerServer服务
    51         TimerServer timerServer=new TimerServer();
    52         timerServer.init();
    53     }
    54 }
    View Code

    第二:soket服务器接收到请求的处理类

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 import java.util.Date;
     9 
    10 /**
    11  * 时间服务器接受socket请求的处理类
    12  * @author sxf
    13  * 继承Runnable接口的线程类
    14  *
    15  */
    16 public class TimerServerHandler implements Runnable {
    17     
    18     private Socket socket;
    19 
    20     public TimerServerHandler(Socket socket) {
    21         this.socket=socket;
    22     }
    23     
    24     /**
    25      * 处理socket请求的线程体
    26      */
    27     @Override
    28     public void run() {
    29         BufferedReader in=null;
    30         PrintWriter out=null;
    31         try {
    32             //获取请求的输入流
    33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
    34             //获取响应请求的输出流
    35             out=new PrintWriter(this.socket.getOutputStream(),true);
    36             
    37             String currentTime=null;
    38             String body=null;
    39             //读取请求输入流的内容获取请求信息
    40             while(true){
    41                 body=in.readLine();
    42                 if(body==null){
    43                     break;
    44                 }
    45                 //打印请求信息
    46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
    47                 
    48                 //处理请求信息
    49                 if("shangxiaofei".equals(body)){
    50                     currentTime=new Date(System.currentTimeMillis()).toString();
    51                 }else{
    52                     currentTime="you is not get time";
    53                 }
    54                 //响应请求信息
    55                 out.println(currentTime);
    56             }
    57             
    58         } catch (IOException e) {
    59             e.printStackTrace();
    60         }finally{
    61             if(in!=null){
    62                 try {
    63                     in.close();
    64                 } catch (IOException e) {
    65                     // TODO Auto-generated catch block
    66                     e.printStackTrace();
    67                 }
    68             }
    69             
    70             if(out!=null){
    71                 out.close();
    72             }
    73             
    74             if(this.socket!=null){
    75                 try {
    76                     socket.close();
    77                 } catch (IOException e) {
    78                     // TODO Auto-generated catch block
    79                     e.printStackTrace();
    80                 }
    81             }
    82             
    83             this.socket=null;
    84         }
    85         
    86         
    87         
    88         
    89     }
    90 
    91 }
    View Code

    第三:向socket服务器发送请求

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 创建一个客户端请求
    11  * @author sxf
    12  *
    13  */
    14 public class TimerClient {
    15     
    16     
    17     
    18     public static void main(String[] args) {
    19         int port=8000;
    20         Socket socket=null;
    21         BufferedReader in=null;
    22         PrintWriter out=null;
    23         try {
    24             socket=new Socket("127.0.0.1",port);
    25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    26             out=new PrintWriter(socket.getOutputStream(),true);
    27             //发送请求
    28             out.println("shangxiaofei!=");
    29             System.out.println("TimerClient.main()send order to server success");
    30             
    31             //等待服务器响应
    32             String resp=in.readLine();
    33             System.out.println("TimerClient.main(Now is:)"+resp);
    34         } catch (Exception e) {
    35             // TODO Auto-generated catch block
    36             e.printStackTrace();
    37         }finally{
    38             if(out!=null){
    39                 out.close();
    40                 out=null;
    41             }
    42             if(in !=null){
    43                 try {
    44                     in.close();
    45                 } catch (IOException e) {
    46                     // TODO Auto-generated catch block
    47                     e.printStackTrace();
    48                 }
    49                 in=null;
    50             }
    51             
    52             if(socket!=null){
    53                 try {
    54                     socket.close();
    55                 } catch (IOException e) {
    56                     // TODO Auto-generated catch block
    57                     e.printStackTrace();
    58                 }
    59             }
    60         }
    61     }
    62 
    63 }
    View Code

    【二】同步阻塞I/O服务端通信模型构造的伪异步通信模型

    一:伪异步socket服务端启动(就是在同步的基础上使用了线程池)

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.IOException;
     4 import java.net.ServerSocket;
     5 import java.net.Socket;
     6 
     7 /**
     8  * 时间服务器
     9  * 基于同步阻塞I/O实现的服务器模型
    10  * @author sxf
    11  *
    12  */
    13 public class TimerServer {
    14     
    15     /**
    16      * 启动timerServer服务器
    17      */
    18     public   void init(){
    19         int port=8000;
    20         //创建Socket服务
    21         ServerSocket server=null;
    22         try {
    23             server=new ServerSocket(port);
    24             System.out.println("TimerServer.init()===>the time server is start in port"+port);
    25             Socket socket=null;
    26             //创建处理socket请求的线程池
    27             TimerServerHandlerExcetorPool pool=new TimerServerHandlerExcetorPool(50, 10000);
    28             
    29             while(true){
    30                 //获取一次socket请求
    31                 socket=server.accept();
    32                 //将请求任务提交到线程池处理
    33                 pool.execute(new TimerServerHandler(socket));
    34             }
    35         } catch (IOException e) {
    36             e.printStackTrace();
    37         }finally{
    38             if(server!=null){
    39                 try {
    40                     server.close();
    41                 } catch (IOException e) {
    42                     // TODO Auto-generated catch block
    43                     e.printStackTrace();
    44                 }
    45             }
    46             server=null;
    47         }
    48         
    49     }
    50 
    51     
    52     public static void main(String[] args) {
    53         //启动timerServer服务
    54         TimerServer timerServer=new TimerServer();
    55         timerServer.init();
    56     }
    57 }
    View Code

    二:伪异步socket服务处理socket请求的线程池

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.util.concurrent.ArrayBlockingQueue;
     4 import java.util.concurrent.ExecutorService;
     5 import java.util.concurrent.ThreadPoolExecutor;
     6 import java.util.concurrent.TimeUnit;
     7 /**
     8  * 处理socket服务器接收到的socket请求的线程池
     9  * @author sxf
    10  *
    11  */
    12 public class TimerServerHandlerExcetorPool {
    13 
    14     private ExecutorService executorService;
    15     
    16     /**
    17      * 初始化线程池
    18      * @param maxPoolSize
    19      * @param queueSize
    20      */
    21     public TimerServerHandlerExcetorPool(int maxPoolSize,int queueSize){
    22         executorService=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
    23     }
    24     
    25     /**
    26      * 提交到线程池,执行socket请求任务
    27      * @param runnable
    28      */
    29     public void execute(Runnable runnable){
    30         executorService.execute(runnable);
    31     }
    32     
    33 }
    View Code

    三:处理请求的Handler类(线程类)

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 import java.util.Date;
     9 
    10 /**
    11  * 时间服务器接受socket请求的处理类
    12  * @author sxf
    13  * 继承Runnable接口的线程类
    14  *
    15  */
    16 public class TimerServerHandler implements Runnable {
    17     
    18     private Socket socket;
    19 
    20     public TimerServerHandler(Socket socket) {
    21         this.socket=socket;
    22     }
    23     
    24     /**
    25      * 处理socket请求的线程体
    26      */
    27     @Override
    28     public void run() {
    29         BufferedReader in=null;
    30         PrintWriter out=null;
    31         try {
    32             //获取请求的输入流
    33             in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
    34             //获取响应请求的输出流
    35             out=new PrintWriter(this.socket.getOutputStream(),true);
    36             
    37             String currentTime=null;
    38             String body=null;
    39             //读取请求输入流的内容获取请求信息
    40             while(true){
    41                 body=in.readLine();
    42                 if(body==null){
    43                     break;
    44                 }
    45                 //打印请求信息
    46                 System.out.println("TimerServerHandler.run()==>the time server receive order:"+body);
    47                 
    48                 //处理请求信息
    49                 if("shangxiaofei".equals(body)){
    50                     currentTime=new Date(System.currentTimeMillis()).toString();
    51                 }else{
    52                     currentTime="you is not get time";
    53                 }
    54                 //响应请求信息
    55                 out.println(currentTime);
    56             }
    57             
    58         } catch (IOException e) {
    59             e.printStackTrace();
    60         }finally{
    61             if(in!=null){
    62                 try {
    63                     in.close();
    64                 } catch (IOException e) {
    65                     // TODO Auto-generated catch block
    66                     e.printStackTrace();
    67                 }
    68             }
    69             
    70             if(out!=null){
    71                 out.close();
    72             }
    73             
    74             if(this.socket!=null){
    75                 try {
    76                     socket.close();
    77                 } catch (IOException e) {
    78                     // TODO Auto-generated catch block
    79                     e.printStackTrace();
    80                 }
    81             }
    82             
    83             this.socket=null;
    84         }
    85         
    86         
    87         
    88         
    89     }
    90 
    91 }
    View Code

    四:客户端发送请求

     1 package com.yeepay.sxf.testbio;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 
     9 /**
    10  * 创建一个客户端请求
    11  * @author sxf
    12  *
    13  */
    14 public class TimerClient {
    15     
    16     
    17     
    18     public static void main(String[] args) {
    19         int port=8000;
    20         Socket socket=null;
    21         BufferedReader in=null;
    22         PrintWriter out=null;
    23         try {
    24             socket=new Socket("127.0.0.1",port);
    25             in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
    26             out=new PrintWriter(socket.getOutputStream(),true);
    27             //发送请求
    28             out.println("shangxiaofei!=");
    29             System.out.println("TimerClient.main()send order to server success");
    30             
    31             //等待服务器响应
    32             String resp=in.readLine();
    33             System.out.println("TimerClient.main(Now is:)"+resp);
    34         } catch (Exception e) {
    35             // TODO Auto-generated catch block
    36             e.printStackTrace();
    37         }finally{
    38             if(out!=null){
    39                 out.close();
    40                 out=null;
    41             }
    42             if(in !=null){
    43                 try {
    44                     in.close();
    45                 } catch (IOException e) {
    46                     // TODO Auto-generated catch block
    47                     e.printStackTrace();
    48                 }
    49                 in=null;
    50             }
    51             
    52             if(socket!=null){
    53                 try {
    54                     socket.close();
    55                 } catch (IOException e) {
    56                     // TODO Auto-generated catch block
    57                     e.printStackTrace();
    58                 }
    59             }
    60         }
    61     }
    62 
    63 }
    View Code
  • 相关阅读:
    使用MyEclipse可视化开发Hibernate实例
    Query查询
    Java Filter过滤机制详解(转载)
    持久化对象的状态转换
    经典SQL语句大全
    持久对象的生命周期
    Mysql命令操作
    hibernate常用的接口和类的方法以及持久化对象的状态变化
    mysql的安装
    Visual C# 2008+SQL Server 2005 数据库与网络开发 10.8 小结
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/5827323.html
Copyright © 2020-2023  润新知