java BIO深入学习

一、BIO的工作原理

传统Io(BIO)的本质就是面向字节流来进行数据传输的
在这里插入图片描述
①:当两个进程之间进行相互通信,我们需要建立一个用于传输数据的管道(输入流、输出流),原来我们传输数据面对的直接就是管道里面一个个字节数据的流动(我们弄了一个 byte 数组,来回进行数据传递),所以说原来的 IO 它面对的就是管道里面的一个数据流动,所以我们说原来的 IO 是面向流的
②:我们说传统的 IO 还有一个特点就是,它是单向的。解释一下就是:如果说我们想把目标地点的数据读取到程序中来,我们需要建立一个管道,这个管道我们称为输入流。相应的,如果如果我们程序中有数据想要写到目标地点去,我们也得再建立一个管道,这个管道我们称为输出流。所以我们说传统的 IO 流是单向的

二、传统的BIO编程实例回顾

网络编程的基本模型是C/S(客户端/服务器端)模型,也就是两个进程之间的通讯,其中服务端提供位置信(绑定ip地址和端口),客户端通过连接操作向服务器端监听的端口地址发起连接请求,基于TCP协议下进行三次握手连接,连接成功后,双方进行socket通讯。
传统的同步阻塞模型开发中,服务端ServerSocket负责绑定ip地址,启动监听端口;客户端Socket负责发起连接操作。连接成功之后,双方通过输入和输出流进行同步阻塞式通信。
基于BIO模式下的通讯,客户端-服务器端是完全同步,完全耦合的。
服务器端代码

public class Server {public static void main(String[] args) {try {System.out.append("服务器端启动。。。");//1.定义ServerSocket对象进行服务端的端口注册ServerSocket serverSocket = new ServerSocket(8080);//2.监听客户端的Socket连接程序Socket socket = serverSocket.accept();//3.从socket对象当中获取到一个字节输入流对象InputStream iStream = socket.getInputStream();//打印输出int len = 0;int ReviceLen = 0;//计算机网络数据是以8bit为一个单元进行发送,我们接收到发送方发送的byte数据//将其转化为utf-8的格式进行输出byte[] recvBuf = new byte[1024];while ((ReviceLen = iStream.read(recvBuf)) != -1) {System.out.println("  客户端说:"+ new String(recvBuf, 0, ReviceLen, "UTF-8"));}} catch (Exception e) {}}
}

客户端代码

public class Client {public static void main(String[] args) throws Exception {//1.创建socket对象请求服务器的连接Socket socket = new Socket("127.0.0.1",8080);//2.从socket对象中获取一个字节输出流、OutputStream oStream = socket.getOutputStream();oStream.write(("你好服务器").getBytes());//以字节流的形式发送数据//4.关闭oStream.flush();}
}

三、BIO模式下的多发和多收消息

服务器端不变,客户端:

public class Client {public static void main(String[] args) throws Exception {//1.创建socket对象请求服务器的连接Socket socket = new Socket("127.0.0.1",8080);//2.从socket对象中获取一个字节输出流、OutputStream oStream = socket.getOutputStream();Scanner scanner = new Scanner(System.in);while (true){System.out.println("请说....");String message = scanner.nextLine();oStream.write(message.getBytes());//4.关闭oStream.flush();}}
}

在这里插入图片描述
在这里插入图片描述

四、BIO模式下接收多个客户端

在上述的案例当中,一个服务端只能接收一个客户端的通信请求,那么如果服务端需要处理很多个客户端的消息通讯请求应该如何处理呢?

当我们启动两个客户端,分别去访问服务器端的时候,我们发现服务器端只连接了一个客户端,并且只能和一个客户端进行通信。
在这里插入图片描述
在这里插入图片描述

什么原因导致了我们服务器只能链接一个客户端

在这里插入图片描述

那如何解决呢?

此时就需要在服务端引入线程了,也就是说客户端发起一次请求,服务端就会创建一个新的线程来处理一个新的线程来处理这个客户端的请求,这样就实现了一个客户端一个线程的模型,图解如下:
在这里插入图片描述

服务器端改进代码

public class Server {public static void main(String[] args) {try {System.out.append("服务器端启动。。。");//1.定义ServerSocket对象进行服务端的端口注册ServerSocket serverSocket = new ServerSocket(8080);while (true){//2.监听客户端的Socket连接程序Socket socket = serverSocket.accept();//创建一个独立的线程来处理也客户端的Socket请求new ServerThreadReader(socket).start();}} catch (Exception e) {e.printStackTrace();}}
}
class ServerThreadReader extends Thread {private Socket socket;public ServerThreadReader(Socket socket) {this.socket = socket;}@Overridepublic void run() {//3.从socket对象当中获取到一个字节输入流对象try {InputStream iStream = socket.getInputStream();//打印输出int len = 0;int ReviceLen = 0;//计算机网络数据是以8bit为一个单元进行发送byte[] recvBuf = new byte[1024];while ((ReviceLen = iStream.read(recvBuf)) != -1) {System.out.println("  客户端说:"+ new String(recvBuf, 0, ReviceLen, "UTF-8"));}} catch (IOException e) {e.printStackTrace();}}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小结

1.每个socket接受到,都会床架一个新的线程,线程的竞争、切换上下文影响性能。
2.每个线程都会占用栈空间和cpu资源
3.并不是每一个socket都进行IO操作,无意义的线程处理
4.客户端的并发访问增加时。服务端将呈现1:1的线程开销,访问量越大,系统将发生线程栈溢出,线程创建失败,最终导致进程宕机或僵死,从而不能对外提供服务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/499070.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

综合实战(volume and Compose)

"让我,重获新生~" MySQL 灾难恢复 熟练掌握挂载卷的使用,将Mysql的业务数据存储在 外部。 实战思想: 使用 MySQL 5.7 的镜像创建容器并创建一个普通数据卷 "mysql-data"用来保存容器中产生的数据。我们需要容器连接到Mysql服务&a…

java008 - Java方法

1、方法概述 1.1 概念 将独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。 1.2 注意事项 方法必须先创建才能使用,该过程称为方法的定义方法创建好不能直接运行,需要手动使用才执行,该过程称为方法的调用 2、方…

观察者模式与发布订阅模式

观察者模式 定义: 观察者模式是一种行为型设计模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 结构图: ES6简易代码实现: //ts环境下…

ai作画在线生成!这8个AI生图工具一定要知道。

过去的2023年被称作AI元年,随之而来的2024,被业内人士称之为AI应用元年,即随着大模型和各类AI应用的涌现速度放缓,人们关注的焦点也从产品层面(有哪些好用的AI应用),转移到AI如何更好地赋能实际…

【Godot4自学手册】第十七节主人公的攻击和敌人的受伤

本节主要学习主人公是如何向敌人发起进攻的,敌人是如何受伤的,受伤时候动画显示,击退效果等。其原理和上一节内容相同,不过有许多细节需要关注和完善。 一、修改Bug 在本节学习之前,我将要对上一节的代码进行完善&am…

androidframework开发面试,阿里P8成长路线

字节跳动Android面经 一面问的 Java 和 Android 基础 1、Jvm虚拟机 2、messageQueue会不会阻塞ui线程 3、对象锁和类锁 4、之字形打印树 5、还有其他的 《Android学习笔记总结最新移动架构视频大厂安卓面试真题项目实战源码讲义》 **完整开源项目:docs.qq.com/doc…

【leetcode】破解闯关密码 模板字符串

/*** param {number[]} password* return {string}*/ var crackPassword function(password) {return minNumspassword.sort((a,b)>{if(${a}${b}-${b}${a}>0){return 1;}else{return -1;}}).join(""); };巧用模板字符串对数组进行排序

二、TensorFlow结构分析(2)

目录 1、会话 1.1 __init__(target,graphNone,configNone) 1.2 会话的run() 1.3 feed操作 TF数据流图图与TensorBoard会话张量变量OP高级API 1、会话 1.1 __init__(target,graphNone,configNone) def session_demo():# 会话的演示# Tensorflow实现加法运算a_t tf.constan…

Vue+SpringBoot打造音乐偏好度推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1.2 我的喜好模块2.1.3 每日推荐模块2.1.4 通知公告模块 2.2 用例图设计2.3 实体类设计2.4 数据库设计 三、系统展示3.1 登录注册3.2 音乐档案模块3.3 音乐每日推荐模块3.4 通知公告模…

继承-学习2

this关键字:指向调用该方法的对象,一般我们是在当前类中使用this关键字,所以我们常说代表本类对象的引用 super关键字:代表父类存储空间的标识(可看作父类对象的引用) 父类: package ven;public class Fu {//父类成员…

【云原生】Spring Cloud Gateway的底层原理与实践方法探究

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:从入门到入魔》 🚀 本…

Win32汇编ListView控件学习

此控件比较复杂;和基础win32控件不同;需要先初始化Windows公共控件库, invoke InitCommonControls 之后才可使用; lvdemo.asm, .386.model flat, stdcalloption casemap :none ; case sensitiveinclude window…