导语
  随着JavaI/O库的不断迭代升级,基于Java 语言的网络编程也开始变的简单,随着异步I/O功能的增强,基于JavaNIO开发的网络服务器也越来越多。很多的互联网大厂都在不断的优化JavaNIO的开发。

  对于网络编程来讲,最为基本的模型就是Server/Client模型,简单的说就是两个线程之间的通信。其中,Server服务端提供的是IP地址以及端口号,客户端通过TCP三次握手连接到服务端指定的IP地址与端口号。然后双方就可以通过Socket进行通信。

  在之前的Java网络开发模型中,ServerSocket主要是负责提供服务端的IP端口等信息。而Socket则是作为客户端向服务端建立连接然后进行输入输出流的同步阻塞方式通信。

  下面就来通过一个小例子来看看关于同步阻塞通信BIO相关的内容。如图所示

  BIO通信模型,在服务端通常会有一个独立的Acceptor线程负责监听客户端的连接,收到客户端发送的连接之后,为每个客户端建立一个新的线程进行处理链路请求,处理完成之后,通过输出流的方式返回给客户端,然后线程进行销毁。这就是比较经典的一请求一应答的通信模型。

  这个模型最大的问题就是不能够弹性伸缩,当客户端的访问量增加之后,服务端的线程数将会与客户端的数量呈1:1的正比关系,由于线程是JVM中比较宝贵的系统资源,在线程数暴涨之后,系统的性能也将下降,随着并发量的逐渐增大,系统会发生线程堆栈溢出、创建新的线程失败等问题,最终就会导致JVM不能提供服务。

  下面就通过一个小例子来进行测试

public class TimeServer {public static void main(String[] args) {int port = 8080;ServerSocket serverSocket = null;try{serverSocket = new ServerSocket(port);System.out.println("The time server is start in port : "+ port);Socket socket = null;while (true){socket = serverSocket.accept();new Thread(new TimeServerHandler(socket)).start();;}} catch (IOException e) {e.printStackTrace();}finally {if (serverSocket!=null){System.out.println("The time server close");try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}serverSocket = null;}}}
}

  运行代码之后,会看到这线程会阻塞到TimeServer类的第25行代码上,也就是 socket = serverSocket.accept(); 。通过一个无限循环来监听客户端的连接,如果没有客户端接入,则主线程阻塞在ServerSocket的accept方法上。

public class TimeServerHandler implements Runnable {private Socket socket;public TimeServerHandler(Socket socket) {this.socket = socket;}@Overridepublic 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("The time server receive order : "+body);currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER";out.println(currentTime);}} catch (IOException e) {if (in!=null){try{in.close();} catch (IOException e1) {e1.printStackTrace();}}if (out!=null){out.close();out = null;}if (this.socket!=null){try {this.socket.close();} catch (IOException e1) {e1.printStackTrace();}this.socket = null;}}}
}

  通过BufferedReader读取数据,如果读取到输入流的结束,则返回null,退出循环,如果读取到非空的值,则会对内容进行判断。然后根据具体的请求要求进行操作。

  TimeClient客户端通过建立Socket连接,发送查询时间到服务端,然后读取到服务端的响应结果并打印出来,然后关闭连接,释放资源。

public class TimeClient {public static void main(String[] args) {int port = 8080;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("QUERY TIME ORDER");System.out.println("Send order 2 server succeed");String resp = in.readLine();System.out.println("Now is : "+resp);} catch (Exception e) {}finally {if (out!=null){out.close();out = null;}if (in!=null){try {in.close();} catch (IOException e) {e.printStackTrace();}in = null;}if (socket!=null){try {socket.close();} catch (IOException e) {e.printStackTrace();}socket=null;}}}
}

  通过整个的实验会发现,BIO主要的问题就是在于每当有一个新的客户端请求接入的时候,服务端就必须创建一个新的线程处理新的连接,并且一个线程只能处理一个客户端的连接请求。这在高性能的互联网领域是行不通的,在高性能互联网领域往往会是同时有成千上万的客户端进行并发请求,这种显然不满足高性能的互联网接入方式。

  为了改进这种模型,结合池化技术和消息队列技术就实现了1个或者多个线程处理多个客户端的模型,但是它的底层还是采用了BIO的方式,所以就被称为是伪异步的实现方式。

Netty从入门到精通-BIO详解相关推荐

  1. Spring Data JPA 从入门到精通~@Query详解

    语法及其源码 public @interface Query {/*** 指定JPQL的查询语句.(nativeQuery=true的时候,是原生的Sql语句)*/String value() def ...

  2. IDEA 入门:安装使用详解(创建项目/包/类、运行/关闭/导入项目、字体/字号设置、常用快捷键等)

    文章目录 前言 一.创建新项目 Project 1.1.选择"Create New Project" 1.2.选择左下角的"Empty Project" 1.3 ...

  3. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  4. 【区块链开发入门】(四) Truffle详解篇2

    由于本篇篇幅较长,因此转为两篇文章.Truffle详解篇篇1请见:link 目录导航页 [区块链开发入门](一) 以太坊的搭建与运行 [区块链开发入门](二) 以太坊的编程接口 [区块链开发入门](三 ...

  5. 视频教程-Oracle数据库从入门到实用教程详解-Oracle

    Oracle数据库从入门到实用教程详解 全栈工程师,2010年从事软件开发以及软件教育培训工作,至今将近十余年,在项目的开发,设计,到管理上积累了丰富的实战经验,教学风格上通俗易懂,问题解答环节一对一 ...

  6. 零基础入门 Unity 之 UGUI 详解专栏 | 寻找C站宝藏

    零基础入门 Unity 之 UGUI 详解专栏 | 寻找C站宝藏 六大推荐理由 理由一:系统 理由二:详细 理由三:专业 理由四:图解 理由五:深度 理由六:实例 一键直达:<UGUI 控件详解 ...

  7. PyTorch入门笔记-matmul函数详解

    PyTorch入门笔记-matmul函数详解 本文转载自:PyTorch入门笔记-matmul函数详解 - 腾讯云开发者社区-腾讯云 (tencent.com) 41409)]

  8. C++入门——上卷(引用详解)

    C++入门--上卷 命名空间的探究 1,命名空间的定义 2,命名空间的使用 缺省参数 1.什么是缺省参数 2,全缺省与半缺省: 引用 1,什么是引用 2,引用的特性 3,常引用 4,使用场景 1,做参 ...

  9. mysql添加两种数据类型_MySQL入门(二) 数据库数据类型详解

    序言 今天去健身了,感觉把身体练好还是不错的,闲话不多说,把这个数据库所遇到的数据类型今天统统在这里讲清楚了,以后在看到什么数据类型,咱度应该认识,对我来说,最不熟悉的应该就是时间类型这块了.但是通过 ...

最新文章

  1. 【错误记录】Groovy 闭包使用报错 ( 闭包中不能直接使用外部对象的方法 | 需要先设置 delegate 代理 )
  2. Java中ListE对象赋值问题(引用传递和值传递)
  3. 怎么导出费用科目凭证明细_公司做账:小规模公司怎么做账?
  4. 1090. Highest Price in Supply Chain (25)
  5. Xcode8更新约束
  6. 基于中文主观性知识库的句子主观性计算项目
  7. 从系统中取得指定资源图像(转载)
  8. Linux上安装Python3和pip3
  9. web测试与app功能测试的区别
  10. SharePoint 入门书籍推荐 转载来源http://www.cnblogs.com/jianyus/p/3513238.html
  11. 最新,最详细的LINUX图文配置教程|之DNS篇(1)
  12. 1. DFT 入门篇-scan chain
  13. MySQL更新行和插入列的语句
  14. STM32F103系列选型
  15. 企业数字化进程中,商业智能 BI 如何降本增效
  16. 图文解读Fcoin发布的FT公链
  17. 前端性能优化-对图片进行后压缩发向后端
  18. 蚂蚁金服“定损宝”现身AI顶级会议NeurIPS 1
  19. Occluded-REID 行人重识别中的遮挡数据集
  20. Git忽略文件(.ignore)以及git status,git diff,git rm命令

热门文章

  1. plsql存储过程修改后怎么保存_分布式基础-存储引擎
  2. DDGScreenShot —图片加各种滤镜高逼格操作
  3. 北京开源人linux运维实战
  4. ant+jenkins+testng+selenium集成环境搭建
  5. Training的第二十二天
  6. LeetCode:Combinations
  7. [置顶] 自己动手写Web容器之TomJetty之六:动态页面引入
  8. ufw禁止IP访问ubuntu服务器
  9. 《参考消息》出现大标题错别字硬伤
  10. 【C语言期末实训】学生学籍管理系统