什么是netty、netty的使用场景、BIO案例演示

154 阅读3分钟

什么是netty

  1. 由jboss提供的一个java开源项目
  2. 是一个异步的、基于事件驱动的网络应用框架,用于快速开发高并发、高可靠的网络IO程序
  3. 主要针对TCP协议下,面向Clients端的高并发,或者Peer-toPeer场景下的大量数据持续输出的应用
  4. 本质是一个NIO,适用于服务器通信相关的多种应用场景
  • 层级与结构
TCP/IP
原生的JDK(IO/网络) => java的io原理和网络编程原理
NIO(IO、网络)
Netty

应用场景

  1. 互联网行业、分布式,阿里Dubbo的RPC框架的使用
  2. 游戏行业(网络游戏)、地图与服务器之间的通信
  3. 大数据领域 AVRO 实现数据文件共享

IO模型

  1. 理解:用什么样的通道进行数据发送和接受,很大程度上决定了程序通信的性能

  2. java支持3种网络编程模型:BIO、NIO、AIO

  3. BIO:一个连接对应一个线程(同步阻塞型)

  4. NIO:同步非阻塞型

  5. AIO:异步非阻塞型 (没有得到广泛使用)

  6. 三种io模型的使用场景

三种io模型适用场景.png

BIO的工作机制

  • 流程
  1. 服务器端启动一个ServerSocket
  2. 客户端启动Socket对服务进行通信,默认情况下服务器端需要对每个客户建立一个线程与之通信
  3. 客户端发出请求后,先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝
  4. 如果有响应,客户端线程会等待请求结束后,再继续执行

BIO原理.png

线程池的7种创建方法

1. Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,
超出的线程会在队列中等待;
2. Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所
需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先
出的执⾏顺序;
4. Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
5. Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执⾏延迟任
务的线程池;
6. Executors.newWorkStealingPool:创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确
定)【JDK1.8 添加】。
7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置
        

案例

BIO案例.png

指令

  1. telnet 127.0.0.1:6666 指定连接
  2. ctrl+] 客户端输入信息
  3. send + 你要输入的信息 (例如: send hello netty )

解答

思路:

  1. 创建一个线程池
  2. 如果有客户端连接,就创建一个线程,与之通信(单独写一个方法
public class BIOServer {
    public static void main(String[] args) throws IOException {
        ExecutorService servicePool = Executors.newCachedThreadPool();
        // 创建ServerSocket
        ServerSocket serverSocket  = new ServerSocket(6666);
        System.out.println("服务器启动了");
        while(true) {
            System.out.println("线程信息"+Thread.currentThread().getId()+"线程
            名"+Thread.currentThread().getName());
            // 监听客户端连接
            System.out.println("等待连接");
            final Socket socket = serverSocket.accept();
            System.out.println("没有连接就会阻塞在上一步,有连接就会打印这句话======》连接到一个客户端");
            // 创建一个线程,与之同行独立写一个方法
            servicePool.execute(new Runnable() {
                @Override
                public void run() {
                    // 可与客户端进行通信
                    hander(socket);
               } });
        }
    }
    public static void hander(Socket socket) {
        System.out.println("线程信息"+Thread.currentThread().getId()+"线程名"+Thread.currentThread().getName());
        byte [] bytes  = new byte[1024];
        // 通过socket获取输入流
        InputStream inputStream = null;
        try {
            inputStream = socket.getInputStream();
            // 循环读取客户端发送的数据
            while(true) {
                System.out.println("线程信息"+Thread.currentThread().getId()+"线程名"+Thread.currentThread().getName());
                System.out.println("read....");
                int read = inputStream.read(bytes);
                if(read!=-1) {
                    System.out.println(new String(bytes,0,read)); // 输入读取到客户端的数据
                }else {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果

BIO案例结果图.png