Netty学习--BIO

一.常见IO模型

1.BIO

BIO是一种传统的同步阻塞的IO模型,每当有一个客户端发送IO请求时,服务端就要创建一个线程进行处理。当数据还未准备好时,当前线程会一直阻塞,占用CPU资源,造成资源浪费,如下图所示

BIO是基于流的形式来进行IO操作的,相较于NIO和AIO模型,在性能上相差较大。

2.NIO

NIO是同步非阻塞IO模型,它是基于缓冲区来实现的。核心主要包括三个部分:Channel、Buffer以及Selector。它会创建一个线程不断去轮询多个 socket 的状态,只有当 socket 真正有读写事件时,才真正调用实际的 IO 读写操作,也就是通过Selector来监听通道的事件,事件发生时,才会调用IO操作,不会造成阻塞。这样就能减少线程的开销以及资源浪费。在进行IO读写操作时,NIO 基于 Channel 和 Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中,如下图所示。

3.AIO

AIO是异步的IO模型,在异步 IO 模型中,当用户线程发起 read 操作之后,立刻就可以开始去做其它的事。从内核的角度来看,当它受到一个 异步 read 之后,它会立刻返回,说明 read 请求已经成功发起了,因此不会对用户线程产生任何 block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它 read 操作完成了。也就说用户线程完全不需要实际的整个 IO 操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接去使用数据。

二.使用场景

1.BIO

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序简单易理解。

2.NIO

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。

3.AIO

AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

三.BIO编程

1.编码流程

1.构建BIO服务端,绑定对应端口

2.创建线程池来管理线程

3.等待客户端连接,通过serverSocket.accept()获取客户端socket

4.实现Runnable接口的run方法,实现数据的读写操作

5.通过telnet来进行测试

2.代码

public class BIOServer {

    public static void main(String[] args) {

        //1.创建线程池
        ExecutorService executor = Executors.newCachedThreadPool();
        //2.通过ServerSocket监听客户端连接,进行io操作
        ServerSocket serverSocket = null;
        try {
            //绑定端口7777    
            serverSocket = new ServerSocket(7777);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //3.轮询监听客户端连接,并执行io操作
        while (true) {
            try {
                //等待客户端连接
                final Socket socket = serverSocket.accept();
                if(socket.isConnected()) {
                    executor.execute(new Runnable() {
                        public void run() {
                            try {
                                //通过字符流输出连接信息至客户端
                                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "GB2312"));
                                bw.write("已连接socketServer");
                                bw.flush();

                                //获取输入流,并转化成字符串输出
                                InputStream inputStream = socket.getInputStream();
                                byte[] buff = new byte[1024];
                                int len = 0;
                                while((len = inputStream.read(buff)) != -1) {
                                    System.out.println(Thread.currentThread().getName() + " : " + new String(buff, 0, len));
                                }
                            } catch (IOException e) {
                                e.printStackTrace();
                            } finally {
                                try {
                                    socket.close();  //关闭socket
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    });
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

3.结果测试

通过命令行输入命令 telnet 127.0.0.1 7777 建立连接

然后输入 ctrl+】 进行文本输入模式

通过send命令发送消息至服务端

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值