导语
  随着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. 字节数与字符数mysql_数据库字段长短之字节与字符
  2. Android之自定义AlertDialog的实现方法(一)
  3. SpringMVC + Apache POI 实现WEB中Excel下载功能
  4. window系统下的堆栈溢出 作者:ipxodi
  5. ArcGis Server开发Web GIS新手体验(二)
  6. mybatis逆向工程generatorConfiguration详细配置
  7. 【BZOJ2326】【codevs2314】数学作业,第100篇博文纪念
  8. apache 启用 gzip压缩
  9. 几何画板手机版_钉钉+几何画板+手写板,网络授课变简单
  10. 一步一步写算法(之查找)
  11. android和webview交互,android webview与原生交互
  12. 相当于jQuery .hide()来设置可见性:隐藏
  13. 《一个程序员的奋斗史》帮我选封面哇! —— 猜封面页数赢赠书活动~
  14. 2019牛客多校第二场E MAZE(线段树 + 矩阵)题解
  15. 巨杉数据库入选2021年广州独角兽创新企业榜单
  16. IEEE Access投稿(Latex模板)——参考文献的生成
  17. java dagger2_mvp+dagger2+retrofit2+rxjava 项目框架 最佳实践
  18. 一款快速搭建局域网http服务器的神器
  19. Android, App常用图标尺寸规范
  20. 松下伺服电机uvw接线图_伺服电机接线图图解

热门文章

  1. Docker Compose 网络介绍
  2. 基于SignalR的站点有连接数限制问题及解决方案
  3. Java enum(枚举)的用法详解(转)
  4. OpenStack securityGroup rule Set
  5. Emacs sql-mode 自动连接数据库 (当前仅支持MySQL)
  6. 双线路接入时IPSec数据不通问题
  7. 如何妥善处理WebBrowser对Javascript的错误问题,阻止JS弹出框,提高用户体验(原创)...
  8. Python私有变量的用法
  9. echarts散点图搭配时间轴
  10. Linux运行级别介绍