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

 

时间: 2024-10-27 03:19:35

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

服务器-java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意

问题描述 java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意 各位大侠好,小弟想问一下问题,搞了一两天没有搞明白的.因为要实现一个UDP传输服务端,于是在网上找了很多资料然后就写了一个.但是写好之后发现有两个很严重的问题,希望各位大哥给点意见或者思路去解决.问题一:启动服务端,同时也启动客户端,客户端传输数据服务器正常接收,但是断开客户端后,再启动客户端,服务器就收不到任何客户端发送的消息,好像是服务器关闭了UDP一样,但是重启服务器后(重新打开UDP)客户端既可以发送信息

开源一个基于nio的java网络程序

   因为最近要从公司离职,害怕用nio写的网络程序没有人能看懂(或许是因为写的不好吧),就调整成了mina(这样大家接触起来非常方便,即使没有socket基础,用起来也不难),所以之前基于nio写的网络程序就开放出来好了!       写的比较挫,大家见谅!       首先是PollServer类,主要处理select,做网络事件的监听和基于FutureTask的数据发送,代码如下: package gs.gate; import gs.gate.handle.ClientHandle; i

Java.nio vs Java.io

Java.nio vs Java.io By Nino Guarnacci on Jun 18, 2009 --- posted by Davide Pisano This document is not a Java.io or a Java.nio manual, or a technical document about Java.io and Java.nio use. It only attempts to compare these two packages, highlightin

我的Java开发学习之旅------&amp;gt;Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常,具体如下: java.nio.charset.MalformedInputException: Input length = 1 at java.nio.charset.CoderResult.throwException(CoderResult.java:260) at java.nio.char

java中nio的socket通信实例程序

虽然Java平台有不少相当不错的一步socket的框架,比如Netty,naga等,但是我们应该知其然并知其所以然. nio是java New IO 的简称,从jdk1.4里提供的新api,Sun官方标榜的特性如下: 为所有的原始类型提供 (Buffer) 缓存支持 字符集编码解码解决方案 Channel:一个新的原始 I/O 抽象 支持锁和内存映射文件的文件访问接口 提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 基本原理 NIO 有一个主要的类Selector,这个类似

java的nio之:浅析I/O模型

也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗.在 进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型.下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后 介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor). 以下是本文的目录大纲: 一.什么是同步?什么是异步? 二.什么是阻塞?什么是非

java的nio之:java的nio系列教程之概述

一:java的nio的核心组件?Java NIO 由以下几个核心部分组成: ==>Channels ==>Buffers ==>Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的API.其它组件,如Pipe和FileLock,只不过是与三个核心组件共同使用的工具类.因此,在概述中我将集中在这三个组件上.其它组 件会在单独的章节中讲到. Channel 和 Buffer 基本上,所有的 IO 在

java的nio之:java的nio的原理

转载:http://weixiaolu.iteye.com/blog/1479656         Java NIO原理图文分析及代码实现 前言: 最近在分析hadoop的RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.可以参考:http://baike.baidu.com/view/32726.htm )机制时,发现hadoop的RPC机制的实现主要用到了两个技术:动态代理(

java的nio之:java的nio系列教程之buffer的概念

一:java的nio的buffer==>Java NIO中的Buffer用于和NIO通道Channel进行交互.==>数据是从通道channel读入缓冲区buffer,从缓冲区buffer写入到通道中channel的.==>缓冲区buffer本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. 二:buffer的基本用法 ==>使用Buffer读写数据一般遵循以下四个步骤: 写入数据到Buffer