同步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同步阻塞服务器的启动

 package com.yeepay.sxf.testbio;

 import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; /**
* 时间服务器
* 基于同步阻塞I/O实现的服务器模型
* @author sxf
*
*/
public class TimerServer { /**
* 启动timerServer服务器
*/
public void init(){
int port=8000;
//创建Socket服务
ServerSocket server=null;
try {
server=new ServerSocket(port);
System.out.println("TimerServer.init()===>the time server is start in port"+port);
Socket socket=null;
while(true){
//获取一次socket请求
socket=server.accept();
//启动一个新线程处理socket请求
new Thread(new TimerServerHandler(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(server!=null){
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
server=null;
} } public static void main(String[] args) {
//启动timerServer服务
TimerServer timerServer=new TimerServer();
timerServer.init();
}
}

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

 package com.yeepay.sxf.testbio;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date; /**
* 时间服务器接受socket请求的处理类
* @author sxf
* 继承Runnable接口的线程类
*
*/
public class TimerServerHandler implements Runnable { private Socket socket; public TimerServerHandler(Socket socket) {
this.socket=socket;
} /**
* 处理socket请求的线程体
*/
@Override
public void run() {
BufferedReader in=null;
PrintWriter out=null;
try {
//获取请求的输入流
in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
//获取响应请求的输出流
out=new PrintWriter(this.socket.getOutputStream(),true); String currentTime=null;
String body=null;
//读取请求输入流的内容获取请求信息
while(true){
body=in.readLine();
if(body==null){
break;
}
//打印请求信息
System.out.println("TimerServerHandler.run()==>the time server receive order:"+body); //处理请求信息
if("shangxiaofei".equals(body)){
currentTime=new Date(System.currentTimeMillis()).toString();
}else{
currentTime="you is not get time";
}
//响应请求信息
out.println(currentTime);
} } catch (IOException e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(out!=null){
out.close();
} if(this.socket!=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} this.socket=null;
} } }

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

 package com.yeepay.sxf.testbio;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; /**
* 创建一个客户端请求
* @author sxf
*
*/
public class TimerClient { public static void main(String[] args) {
int port=8000;
Socket socket=null;
BufferedReader in=null;
PrintWriter out=null;
try {
socket=new Socket("127.0.0.1",port);
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream(),true);
//发送请求
out.println("shangxiaofei!=");
System.out.println("TimerClient.main()send order to server success"); //等待服务器响应
String resp=in.readLine();
System.out.println("TimerClient.main(Now is:)"+resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(out!=null){
out.close();
out=null;
}
if(in !=null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
in=null;
} if(socket!=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} }

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

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

 package com.yeepay.sxf.testbio;

 import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; /**
* 时间服务器
* 基于同步阻塞I/O实现的服务器模型
* @author sxf
*
*/
public class TimerServer { /**
* 启动timerServer服务器
*/
public void init(){
int port=8000;
//创建Socket服务
ServerSocket server=null;
try {
server=new ServerSocket(port);
System.out.println("TimerServer.init()===>the time server is start in port"+port);
Socket socket=null;
//创建处理socket请求的线程池
TimerServerHandlerExcetorPool pool=new TimerServerHandlerExcetorPool(50, 10000); while(true){
//获取一次socket请求
socket=server.accept();
//将请求任务提交到线程池处理
pool.execute(new TimerServerHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(server!=null){
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
server=null;
} } public static void main(String[] args) {
//启动timerServer服务
TimerServer timerServer=new TimerServer();
timerServer.init();
}
}

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

 package com.yeepay.sxf.testbio;

 import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 处理socket服务器接收到的socket请求的线程池
* @author sxf
*
*/
public class TimerServerHandlerExcetorPool { private ExecutorService executorService; /**
* 初始化线程池
* @param maxPoolSize
* @param queueSize
*/
public TimerServerHandlerExcetorPool(int maxPoolSize,int queueSize){
executorService=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(queueSize));
} /**
* 提交到线程池,执行socket请求任务
* @param runnable
*/
public void execute(Runnable runnable){
executorService.execute(runnable);
} }

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

 package com.yeepay.sxf.testbio;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date; /**
* 时间服务器接受socket请求的处理类
* @author sxf
* 继承Runnable接口的线程类
*
*/
public class TimerServerHandler implements Runnable { private Socket socket; public TimerServerHandler(Socket socket) {
this.socket=socket;
} /**
* 处理socket请求的线程体
*/
@Override
public void run() {
BufferedReader in=null;
PrintWriter out=null;
try {
//获取请求的输入流
in=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
//获取响应请求的输出流
out=new PrintWriter(this.socket.getOutputStream(),true); String currentTime=null;
String body=null;
//读取请求输入流的内容获取请求信息
while(true){
body=in.readLine();
if(body==null){
break;
}
//打印请求信息
System.out.println("TimerServerHandler.run()==>the time server receive order:"+body); //处理请求信息
if("shangxiaofei".equals(body)){
currentTime=new Date(System.currentTimeMillis()).toString();
}else{
currentTime="you is not get time";
}
//响应请求信息
out.println(currentTime);
} } catch (IOException e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(out!=null){
out.close();
} if(this.socket!=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} this.socket=null;
} } }

四:客户端发送请求

 package com.yeepay.sxf.testbio;

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket; /**
* 创建一个客户端请求
* @author sxf
*
*/
public class TimerClient { public static void main(String[] args) {
int port=8000;
Socket socket=null;
BufferedReader in=null;
PrintWriter out=null;
try {
socket=new Socket("127.0.0.1",port);
in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new PrintWriter(socket.getOutputStream(),true);
//发送请求
out.println("shangxiaofei!=");
System.out.println("TimerClient.main()send order to server success"); //等待服务器响应
String resp=in.readLine();
System.out.println("TimerClient.main(Now is:)"+resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(out!=null){
out.close();
out=null;
}
if(in !=null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
in=null;
} if(socket!=null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} }

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

  1. Netty权威指南之BIO(Block Input/Output,同步阻塞I/O通信)通信模型

    网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口),客户端通过连接操作向服务端监听的地址发起连接请求,通过三次握手建 ...

  2. (转)Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    原文出自:http://blog.csdn.net/anxpp/article/details/51512200 1.BIO编程 1.1.传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间 ...

  3. Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  4. 从同步阻塞聊到Java三种IO方式

    本文总结自 https://zhuanlan.zhihu.com/p/34408883, https://www.zhihu.com/question/19732473中愚抄的回答, http://b ...

  5. 面试中常问的五种IO模型和BIO,NIO,AIO

    一,五种IO模型: 一个IO操作可以分为两个步骤:发起IO请求和实际的IO操作例如:1.操作系统的一次写操作分为两步:第一步,将数据从用户空间拷贝到系统空间:第二步,从系统空间往网卡写.2.一次读操作 ...

  6. java aio nio bio

    转自:http://blog.csdn.NET/liuxiao723846/article/details/45066095 Java中的IO主要源自于网络和本地文件 IO的方式通常分为几种,同步阻塞 ...

  7. I/O模型之四:Java 浅析I/O模型(BIO、NIO、AIO、Reactor、Proactor)

    目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...

  8. Java之NIO,BIO,AIO

    Hollis知识星球的一些学习笔记,有兴趣的朋友可以微信搜一下 什么是NIO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口.它对于任何计算机系统都非常关键,因而所有 ...

  9. Java IO 学习(四)BIO/NIO

    本文会尝试介绍Java中BIO与NIO的范例与原理 使用的模型非常简单:服务器--客户端模型,服务器会将客户端发送的字符串原样发回来.也就是所谓的echo server. BIO 也就是所谓的Sock ...

随机推荐

  1. java基础-006

    37.JDBC JDBC是允许用户在不同数据库之间做选择的一个抽象层.JDBC允许开发者用JAVA写数据库引用程序,而不需要关心底层特定数据库的细节. 38.驱动(Driver) 在JDBC中的角色 ...

  2. C++学习之静态成员

    一.静态数据成员 C++允许将类的数据成员定义为静态成员.静态数据成员是属于类的,整个类只有一个备份,相当于类的全局变量,能够被该类的所有对象共用. 1.静态成员的声明 在类数据成员的声明前加上关键字 ...

  3. 添加Sql作业,新建步骤出现:从IClassFactory为CLSID为{AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2}的COM组件创建实例失败,原因是出现以下错误:c001f011。的解决方法

    32位操作系统: 打开运行(命令提示符), 一.输入 cd c:\windows\system32 进入到c:\windows\system32路径中 二.输入 regsvr32 "C:\P ...

  4. EAX、ECX、EDX、EBX寄存器的作用

    注意:在计算加法时,实在32位的累加器上进行,并注意类型之间的转换,数据的截取问题 一般寄存器:AX.BX.CX.DXAX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器 索引暂存器 ...

  5. fragment的一些bug

    自从Android3.0引入了Fragment之后,使用Activity去嵌套一些Fragment的做法也变得更加流行,这确实是 Fragment带来的一些优点,比如说:Fragment可以使你能够将 ...

  6. python中的面向对象编程

    在python中几乎可以完成C++里所有面向对象编程的元素. 继承:python支持多继承: class Derived(base1, base2, base3): pass 多态:python中的所 ...

  7. VS2013 JS 跟踪

    VS2013JS  跟踪 1.在页面对应的cs文件中设置断点,F10单步执行. 2.单步执行调试会自然而然执行到JS里面.

  8. Http请求与响应格式

    原文:http://www.cnblogs.com/z941030/p/4699779.html Http协议对浏览器发出的Request格式以及对Web服务器发出的Response格式有具体的规定. ...

  9. 深入分析:Fragment与Activity交互的几种方式(一,使用Handler)

    这里我不再详细介绍那写比较常规的方式,例如静态变量,静态方法,持久化,application全局变量,收发广播等等. 首先我们来介绍使用Handler来实现Fragment与Activity 的交互. ...

  10. 关于EOF和循环体的搭配使用。

    在oj中,变成如果有EOF和循环体的话,可能网页输入一个东西之后会输入另一个不知道是什么鬼,所以会造成这种情况.可能在输入应该输入的值以后还有一个值一起输入了,导致这种事情的发生. 比较两个图片观察 ...