Netty学习(1):IO模型之BIO

概述

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

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

IO模型

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

  • BIO:是最传统的Java IO模型,采用的方式为服务器新接受到一个连接,就建立一个线程,但是如果这个连接不做任何事情,该线程也会被创建,闲置着,增加不必要的开销。
  • NIO:服务器用一个线程处理多个请求,将所有请求注册到一个线程管理的多路复用器(Selector)上。适用于连接数量多,但连接比较轻量的服务上,如聊天,弹幕等。
  • AIO:其特点是由OS完成后,才通知服务端程序启动程序来处理,使用场景为相册服务器等。因不是很清楚具体实现,因此在这不展开了。

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和端口,直接连接发送数据即可。

实现效果

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

然后,我们启动客户端1,服务端会启动一个线程来接受并处理请求。

BIO实现问题

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

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

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

备注

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

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

原文地址:https://www.cnblogs.com/JRookie/p/12302213.html

时间: 2024-08-06 23:54:35

Netty学习(1):IO模型之BIO的相关文章

Java IO模型:BIO、NIO、AIO

Java IO模型:BIO.NIO.AIO 本来是打算直接学习网络框架Netty的,但是先补充了一下自己对Java 几种IO模型的学习和理解.分别是 BIO.NIO.AIO三种IO模型. IO模型的基本说明 BIO模型图 缺点: 如果有很多个Client,则会产生很多个线程.压力主要是在服务器端.客户端的压力并不大. 另外建立连接之后,并不是在时时刻刻的使用.会有空间时间. 会阻塞. NIO模型图 特点: 事件驱动 多路复用 Netty底层使用的NIO模型 AIO模型 目前还未得到广泛运用.异步

IO模型之BIO代码详解及其优化演进

一.BIO简介 BIO是java1.4之前唯一的IO逻辑,在客户端通过socket向服务端传输数据,服务端监听端口.由于传统IO读数据的时候如果数据没有传达,IO会一直等待输入传入,所以当有请求过来的时候,新起一条线程对数据进行等待.处理,导致每一个链接都对应着服务器的一个线程. BIO是同步阻塞的,如图所示: 二.原理简述 BIO对应linux io模型的阻塞IO,服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接

5月2日 python学习总结 IO模型

IO模型 1.阻塞IO 2.非阻塞IO 3.多路复用IO 4.异步IO 一.阻塞IO blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了. 实际上,除非特别指定,几乎所有的IO接口 ( 包括socket接口 ) 都是阻塞型的. 所谓阻塞型接口是指系统调用(一般是IO接口)不返回调用结果并让当前线程一直阻塞,只有当该系统调用获    得结果或者超时出错时才返回. 在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大

从底层入手,图解 Java NIO BIO MIO AIO 四大IO模型与原理

目录 写在前面 1.1. Java IO读写原理 1.1.1. 内核缓冲与进程缓冲区 1.1.2. java IO读写的底层流程 1.2. 四种主要的IO模型 1.3. 同步阻塞IO(Blocking IO) 1.4. 同步非阻塞NIO(None Blocking IO) 1.5. IO多路复用模型(I/O multiplexing) 1.6. 异步IO模型(asynchronous IO) 小结一下: 写在最后 疯狂创客圈 百万级流量 高并发实战 疯狂创客圈 Java 分布式聊天室[ 亿级流量

2. 彤哥说netty系列之IO的五种模型

你好,我是彤哥,本篇是netty系列的第二篇. 欢迎来我的公从号彤哥读源码系统地学习源码&架构的知识. 简介 本文将介绍linux中的五种IO模型,同时也会介绍阻塞/非阻塞与同步/异步的区别. 何为IO模型 对于一次IO操作,数据会先拷贝到内核空间中,然后再从内核空间拷贝到用户空间中,所以一次read操作,会经历两个阶段: (1)等待数据准备 (2)数据从内核空间拷贝到用户空间 基于以上两个阶段就产生了五种不同的IO模式. 阻塞IO 从进程发起IO操作,一直等待上述两个阶段完成. 两阶段一起阻塞

深入了解Netty【四】IO模型

引言 IO模型就是操作数据输入输出的方式,在Linux系统中有5大IO模型:阻塞式IO模型.非阻塞式IO模型.IO复用模型.信号驱动式IO模型.异步IO模型. 因为学习Netty必不可少的要了解IO多路复用模型,本篇是基础. 名词概念 阻塞:指向调用方,在调用结果返回之前,调用方线程会挂起,直到结果返回. 非阻塞:指向调用方,在调用结果返回之前,调用方线程会处理其他事情,不会阻塞. 同步:指向被调用方,被调用方得到结果后再返回给调用方. 异步:指向被调用方,被调用方先应答调用方,然后计算结果,最

python学习笔记(IO模型)

1.IO模型介绍: io模型一般有五种: * blocking IO         * nonblocking IO         * IO multiplexing         * signal driven IO         * asynchronous IO 但是 signal driven IO(信号驱动IO)在实际中并不常用,所以只介绍其他四中IO模型 另当IO发生时涉及的对象和步骤.对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调

Python学习:并发编程之IO模型

本节内容: I/O模型介绍 阻塞I/O(blocking IO) 非阻塞I/O(non-blocking IO) 多路复用I/O(IO multiplexing) 异步I/O(Asynchronous I/O) IO模型比较分析 selectors模块 一 IO模型介绍 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wik

IO模型学习笔记

一.IO类型分类: 同步和异步:关注的是消息通知机制 同步(synchronous):调用发出之后不会立即发出返回,但一旦返回就是最终结果 异步(asynchronous):调用发出之后,被调用者会立即返回消息,但返回的结果并非是最终结果,被调用者通过状态机制或者消息通知机制来通知调用者:即通过回调函数来处理结果 阻塞和非阻塞:关注的是调用者等待调用结果(消息.返回值)的状态 阻塞:调用结果返回之前,调用者(调用线程)会被挂起,处于不可中断的睡眠状态(Uninterruptable),调用者只有