首页 > 编程语言 >netty高性能编程-第2章Java BIO编程

netty高性能编程-第2章Java BIO编程

时间:2022-10-30 00:23:45浏览次数:57  
标签:netty Java BIO 编程 System 线程 println 连接 客户端

2.1 IO模型

  • I/O 模型简单的理解:就是用什么样的通道进行数据的发送和接收,很大程度上决定了程序通信的性能
  • Java共支持3种网络编程模型/IO模式:BIO、NIO、AIO
  • Java BIO : 同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销 【简单示意图】
  • Java NIO : 同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求就进行处理 【简单示意图】
  • Java AIO(NIO.2) : 异步非阻塞,AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用

2.2BIO、NIO、AIO适用场景分析

  • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序简单易理解。
  • NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。
  • AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

2.3JavaBIO基本介绍

  • Java BIO 就是传统的java io编程,其相关的类和接口在 java.io
  • BIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)。
  • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,程序简单易理解

BIO编程简单流程

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

实例说明

1)使用BIO模型编写一个服务器端,监听6666端口,当有客户端连接时,就启动一个线程与之通讯。

2)要求使用线程池机制改善,可以连接多个客户端。

3)服务器端可以接收客户端发送的数据(telnet 方式即可)。

BIOServer.java

public class BIOServer {
    public static void main(String[] args) throws Exception {
        //线程池机制
        //思路
        //1. 创建一个线程池
        //2. 如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器启动了");
        while (true) {
            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            //监听,等待客户端连接
            System.out.println("等待连接....");
            final Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");
            //就创建一个线程,与之通讯(单独写一个方法)
            newCachedThreadPool.execute(new Runnable() {
                public void run() { //我们重写
                    //可以和客户端通讯
                    handler(socket);
                }
            });
        }
    }

    //编写一个handler方法,和客户端通讯
    public static void handler(Socket socket) {
        try {
            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            byte[] bytes = new byte[1024];
            //通过socket 获取输入流
            InputStream inputStream = socket.getInputStream();
            //循环的读取客户端发送的数据
            while (true) {
                System.out.println("线程信息 id =" + 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 (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("关闭和client的连接");
            try {
                socket.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

使用nc localhost 6666来进行测试即可。

JavaBIO问题分析

1)每个请求都需要创建独立的线程,与对应的客户端进行数据 Read,业务处理,数据 Write 。

2)当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。

3)连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费

标签:netty,Java,BIO,编程,System,线程,println,连接,客户端
From: https://www.cnblogs.com/hanxuefeng/p/16840290.html

相关文章

  • java 二维数组
    publicclassArrayTwo{publicstaticvoidmain(String[]args){int[][]arr={{1,2,3},{11,223,44}};......
  • Java如何获取当前的jar包路径以及如何读取jar包中的资源
    如何加载jar包中的资源。1.比如说我要得到背景图片,源代码中它是/src/UI/image/background.jpg那么在jar包中它的路径应该是/UI/image/background.jpg路径最前面的/......
  • JAVA-事件监听机制
    packagecom.itheima;importjavax.swing.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;publicclassJFrame11{publicstati......
  • JavaScript
    JavaScriptJavaScript(JS)是一种脚本语言,可以用来更改页面内容,控制多媒体,制作图像动画等.在body标签里面写一个script标签,在script标签里面编写JavaScript代码......
  • JavaWeb-MySQL基础
    JavaWeb-MySQL基础1,数据库相关概念1.1数据库存储和管理数据的仓库,数据是有组织的进行存储。数据库英文名是DataBase,简称DB。数据库就是将数据存储在硬盘上,可......
  • Java顺序结构和分支结构
    Java顺序结构和分支结构1.*顺序结构任何编程语言中最常见的程序结构就是顺序结构。顺序结构就是程序从上到下逐行地执行,中间没有任何判断和跳转。如果main方法的多行代......
  • 编程开发-面试-数据分析视频教程阿里云盘资源大全
    编程开发-面试-数据分析教程合集6.6T(最全)Python编程教程合集(80套207GB)Java-30套Web-28套C-C++29套Go-15套Spring-29套Linux-10套面试通关人工智能_云计算R......
  • JAVA-考勤查询
    packagecom.itheima;importjavax.swing.*;publicclassJFrame09{publicstaticvoidmain(String[]args){JFramejf=newJFrame();jf.s......
  • socket编程的常见问题
    英文小册原文地址:​​beej.us/guide/bgnet…​​作者:Beej中文翻译地址:​​www.chanmufeng.com/posts/netwo…​​1.我从哪获取这些头文件资料?如果你的系统中没有自带这些文......
  • java8 stream按某个字段分组,允许分组字段是null
    Map<String,List<Dto>>deviceMap=deviceList.stream().collect(Collectors.groupingBy(Dto::getFlowId));场景:如果getFlowId是null.就会包以下错误elementcannotb......