Java BIO 网络编程 | Netty 前期知识(一)

简介: Java BIO 网络编程 | Netty 前期知识(一)

微信截图_20220525191540.png


一步一步走来,之前去学习了JUC并发编程知识,现在终于到Java IO网络编程啦,难啊。


一、BIO介绍


引入: 随着技术的发展,两个或以上的程序必然需要进行交互,于是提供了一种端到端的通信,相当于对传输层的一种封装,对于开发人员而言隐藏了传输的细节,将这些固定的“套路”抽象出来,提供一种端到端的通信,可以使我们更加专注于业务的开发。而BIO只是其中一种。


Java BIO (old )就是传统的 Java I/O 编程,其相关的类和接口在 java.io,另外Java BIO是同步并阻塞(传统阻塞型),服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。效率较低,资源容易被浪费。


阻塞和非阻塞


阻塞和非阻塞指的是执行一个操作是等操作结束再返回,还是马上返回。


比如餐馆的服务员为用户点菜,当有用户点完菜后,服务员将菜单给后台厨师,此时有两种方式:


  • 第一种:就在出菜窗口等待,直到厨师炒完菜后将菜送到窗口,然后服务员再将菜送到用户手中;(阻塞方式)


  • 第二种:等一会再到窗口来问厨师,某个菜好了没?如果没有先处理其他事情,等会再去问一次;(非阻塞的)


二、BIO模型


微信截图_20220525191655.png


流程分析:


  1. 首先需要启动一个ServerSocket服务端,用来供客户端连接


  1. 然后再启动ClientSocket客户端,与服务器进行连接通信。(注:默认情况下,每个客户端与服务端都是单独的一个线程通信,不管使用不使用)


  1. 在客户端发出请求后,会先询问服务器端是否可以有线程响应,有以下两种结果:


  • 如若有线程响应,客户端会阻塞等待请求结束后,再继续执行;


  • 假如没有线程响应则会等待响应,或者直接被拒绝


三、代码案例


1)案例:


我们使用BIO模型写一个服务器端,监听8888端口,当有客户端连接时,就启动一个线程与它通讯。


编程思路:


  1. 创建一个线程池


  1. 创建ServerSocket对象 服务器套接字(ServerSocket)等待通过网络传入的请求。


  1. 如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)


  1. 获得 Socket对象, 用于连接通信


  1. 编写一个handler方法,和客户端通讯,读取客户端发过来的信息


package com.crush.bio;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
 * @Author: crush
 * @Date: 2021-08-23 11:51
 * version 1.0c
 */
public class BioServer {
    public static void main(String[] args) throws Exception {
        //1. 创建一个线程池
        ExecutorService newCachedThreadPool = new ThreadPoolExecutor(0,
                Integer.MAX_VALUE,
                60L,
                TimeUnit.SECONDS,
                new SynchronousQueue<>(),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        //2、创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器启动了");
        while (true) {
            System.out.println("线程信息id = " + Thread.currentThread().getId() + "名字 = " + Thread.currentThread().getName());
            //监听,等待客户端连接
            System.out.println("等待连接....");
            //3.侦听要与此套接字建立的连接并接受它。 该方法阻塞,直到建立连接。
            final Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");
            //4、就创建一个线程,与之通讯(单独写一个方法)
            newCachedThreadPool.execute(() -> {
                //可以和客户端通讯
                handler(socket);
            });
        }
    }
    /**
     * 编写一个handler方法,和客户端通讯,读取客户端发过来的信息
     * @param socket
     */
    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();
            }
        }
    }
}


这是一个经典的每连接每线程的模型,之所以使用多线程,主要原因在于socket.accept()、socket.read()、socket.write()三个主要函数都是同步阻塞的,当一个连接在处理I/O的时候,系统是阻塞的,如果是单线程的话必然就挂死在那里;但CPU是被释放出来的,开启多线程,就可以让CPU去处理更多的事情。


2)测试步骤:


  1. 打开cmd命令输入telnet localhost 8888


QQ截图20220525193101.png


  1. 会进入到telnet页面

微信截图_20220525193140.png


  1. 然后在telnet 命令窗口中按下 CTRL+]

微信截图_20220525193210.png


  1. 发送信息命令 是 send 信息


QQ截图20220525193230.png


  1. 控制台输出


QQ截图20220525193308.png


客户端


客户端我也有写的哈😁


package com.crush.bio;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class BIOEchoClient {
    public static void main(String[] args) throws Exception{
        Socket client = new Socket("localhost",8888);
        PrintStream out = new PrintStream(client.getOutputStream());
        boolean flag = true;
        while (flag){
            Scanner scanner = new Scanner(System.in);
            String inputData = scanner.nextLine().trim();
            out.println(inputData);
            if ("byebye".equalsIgnoreCase(inputData)){
                flag = false;
                System.out.println("和客户端说再见拉!!!");
            }
        }
        client.close();
    }
}


这个测试就不说了哈,这个蛮简单的。


3)可能会出现的问题


我们使用telnet命令来测试,默认Windows这个命令是关闭的,就会出现和我一样的问题。


微信截图_20220525193357.png


打开方式:打开控制面板,点程序,然后再点这个进行选择。


微信截图_20220525193428.png


微信截图_20220525193451.png


四、BIO存在的缺陷


BIO的最大缺陷就是在于每个请求都需要创建独立的线程进行连接通讯,这样会造成以下几点问题:


  1. 当并发数上升到较大的时候,需要创建大量线程来处理,容易给系统造成极大的压力,其次创建太多线程、销毁太多线程,占用系统资源较大。


  1. 如果建立连接后,当前线程任务较小,较短,然后之后没有数据可读,则线程会一直阻塞在Read操作上,造成资源的浪费。


五、自言自语


最近在持续更新中,如果你觉得对你有所帮助,也感兴趣的话,关注我吧,让我们一起学习,一起讨论吧。


在学习路上充满好奇心,明白思考的重要性,是支持我一直学习下去的积极推动力吧。希望你也能喜欢上编程!😁


热爱生活,享受生活!!!无论在哪里,无论此时的生活多么艰难,都要记得热爱生活!!!相信总会有光来的。


你好,我是博主宁在春,Java学习路上的一颗小小的种子,也希望有一天能扎根长成苍天大树。


希望与君共勉😁


我们:待别时相见时,都已有所成


目录
相关文章
|
9月前
|
存储 监控 安全
单位网络监控软件:Java 技术驱动的高效网络监管体系构建
在数字化办公时代,构建基于Java技术的单位网络监控软件至关重要。该软件能精准监管单位网络活动,保障信息安全,提升工作效率。通过网络流量监测、访问控制及连接状态监控等模块,实现高效网络监管,确保网络稳定、安全、高效运行。
191 11
|
4月前
|
弹性计算 网络协议 Java
Netty基础—2.网络编程基础二
本文介绍了网络编程的基本概念和三种主要模式:BIO(阻塞IO)、AIO(异步IO)和NIO(非阻塞IO)。BIO模型通过为每个客户端连接创建一个线程来处理请求,适合客户端较少的情况,但在高并发下性能较差。AIO模型通过异步IO操作,允许操作系统处理IO,适合高并发场景,但编码复杂且Linux支持有限。NIO模型通过Selector实现多路复用,适合高并发且性能要求高的场景。文章还详细介绍了NIO中的Buffer、Selector、Channel等核心组件,并提供了NIO的实战开发流程和代码示例。
|
4月前
|
监控 网络协议 Java
Netty基础—1.网络编程基础一
本文详细介绍了网络通信的基础知识,涵盖OSI七层模型、TCP/IP协议族及其实现细节。首先解释了OSI模型各层功能,如物理层负责数据通路建立与传输,数据链路层提供无差错传输等。接着探讨了TCP/IP协议,包括TCP和UDP的特点、三次握手与四次挥手过程,以及如何通过确认应答和序列号确保数据可靠性。还分析了HTTP请求的传输流程和报文结构,并讨论了短连接与长连接概念。 此外,解析了Linux下的IO模型,包括阻塞IO、非阻塞IO、IO复用(select/poll/epoll)、信号驱动IO和异步IO的特点与区别,强调了epoll在高并发场景下的优势及其水平触发和边缘触发两种工作模式。
|
6月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
236 23
|
7月前
|
安全 网络协议 Java
Java网络编程封装
Java网络编程封装原理旨在隐藏底层通信细节,提供简洁、安全的高层接口。通过简化开发、提高安全性和增强可维护性,封装使开发者能更高效地进行网络应用开发。常见的封装层次包括套接字层(如Socket和ServerSocket类),以及更高层次的HTTP请求封装(如RestTemplate)。示例代码展示了如何使用RestTemplate简化HTTP请求的发送与处理,确保代码清晰易维护。
|
7月前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
221 0
|
9月前
|
JSON 算法 Java
Nettyの网络聊天室&扩展序列化算法
通过本文的介绍,我们详细讲解了如何使用Netty构建一个简单的网络聊天室,并扩展序列化算法以提高数据传输效率。Netty的高性能和灵活性使其成为实现各种网络应用的理想选择。希望本文能帮助您更好地理解和使用Netty进行网络编程。
117 12
|
10月前
|
网络协议 Java 物联网
Java网络编程知识点
Java网络编程知识点
136 13
|
10月前
|
消息中间件 编解码 网络协议
Netty从入门到精通:高性能网络编程的进阶之路
【11月更文挑战第17天】Netty是一个基于Java NIO(Non-blocking I/O)的高性能、异步事件驱动的网络应用框架。使用Netty,开发者可以快速、高效地开发可扩展的网络服务器和客户端程序。本文将带您从Netty的背景、业务场景、功能点、解决问题的关键、底层原理实现,到编写一个详细的Java示例,全面了解Netty,帮助您从入门到精通。
1076 0
|
10月前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?

热门文章

最新文章