Netty学习(1):IO模型之BIO
来源:     阅读:527
云上智慧
发布于 2020-04-24 16:45
查看主页

概述

Netty其实就是一个异步的、基于事件驱动的框架,其作用是用来开发高性能、高可靠的IO程序。

因而下面就让我们从Java的IO模型来逐渐深入学习Netty。

IO模型

IO模型简单来说,就是采用如何的方式来进行数据的接受和发送,由于存在着发送方和接收方两个角色,因而IO模型一般分为以下3类:BIO(同步阻塞)、NIO(同步非阻塞)、AIO(异步非阻塞)。其3者的区别如下:

BIO代码实现

使用BIO模型来实现一个服务器端和用户端,并采用线程池的概念,使其可以连接多个用户端。

服务端

首先,让我们来看建立一个服务端需要哪些步骤:

// 创立线程池,假如有连接,就创立一个线程  ps:这里手动指定参数创立线程池会更好,但这里由于不是重点,因而就采用默认的线程池来实现。        ExecutorService executorService = Executors.newCachedThreadPool();        // create ServerSocket        ServerSocket serverSocket = new ServerSocket(6666);        System.out.println("服务端建立,监听!!!");        while (true) {            System.out.println("thread info0 id : " + Thread.currentThread().getId() + " \tname: " + Thread.currentThread().getName());            // waiting for client            System.out.println("等待用户端连接");            // The method blocks until a connection is made.            final Socket socket = serverSocket.accept();            System.out.println("用户端连接成功");            // create a thread for communicated            executorService.execute(new Runnable() {                @Override                public void run() {                    handler(socket);                }            });        }

上述代码就是一个服务器端启动的代码实例,那么该如何解决用户端发送的数据呢。

    public static void handler(Socket socket) {        try (InputStream inputStream = socket.getInputStream();             OutputStream outputStream = socket.getOutputStream();             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));             PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true)) {            System.out.println("thread info1 id : " + Thread.currentThread().getId() + " \tname: " + Thread.currentThread().getName());            String expression;            String result;            while (true) {                System.out.println("thread info2 id : " + Thread.currentThread().getId() + " \tname: " + Thread.currentThread().getName());                //BufferedReader.readLine()会读满缓冲区或者者在读到文件末尾(遇到:"/r"、"/n"、"/r/n")才返回                System.out.println("等待读取数据");                if ((expression = bufferedReader.readLine()) == null) {                    break;                }                System.out.println("result: " + expression);            }        } catch (IOException e) {            System.out.println(e);        } finally {            System.out.println("关闭和client连接!!!");            try {                socket.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }

在这里我们采用循环读取的形式来解决用户端发送的数据,并将其进行输出。

用户端

 // 发送        try (Socket socket = new Socket(InetAddress.getByName("localhost"), 6666);             OutputStream outputStream = socket.getOutputStream()) {            String data = "0A,3,863921030884418,23.178061,0,113.225998,0,2020/01/18 17:28:30,051,4,FF,";            data = getData(data) + "\n";            outputStream.write(data.getBytes());        } catch (Exception e) {            System.out.println(e);        }

用户端的代码就很简单了,指定IP和端口,直接连接发送数据就可。

实现效果

首先我们启动服务端,可以看到如下输出,说明服务端已经被启动起来了,等待用户端连接。

BIO服务端启动

而后,我们启动用户端1,服务端会启动一个线程来接受并解决请求。

BIO请求解决

BIO实现问题

上述就是一个BIO程序实现的Demo版本,这也就是BIO的优点所在,其实现简单,代码逻辑也十分的简洁明了。但其有几个很重要的问题没有处理。

  1. 对应于每个请求都要创立一个来处理,即便有线程池的存在,也会造成很大的线程资源损耗;
  2. handler() 代码中,我们可以看到其是在线程里解决的,但假如线程创立完成后,发现没有数据需要读写,那么其则会阻塞在 read 操作中,影响性能。

正由于BIO有着这许多问题,因而Java官方在1.4后引入了NIO的概念,来完善Java的IO模型,因而,在这里我们只要要理解这种模型就可,知道其会产生什么问题以及产生的起因,接下里,我们把重点放在NIO上,而这也是Netty实现的基础。

备注

本文中代码已上传到GitHub上,地址为 wb1069003157/nettyPre-research ,欢迎大家来探讨,讨论。

iceWang公众号

文章在公众号「iceWang」第一手升级,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 服务器应用
相关推荐
给在校程序员的良心建议
网络性能测试工具:ipert,netperf,qperf比照分析
bt宝塔控制面板mysql频繁自动停止详细解决办法
没有微服务项目经验,就别去面试官那里送人头了
交大博士程序员内推大公司面试被拒,听到起因后蒙了
首页
搜索
订单
购物车
我的