Java BIO基本介绍
- Java BIO 就是传统的 java io 编程,其相关的类和接口在 java.io
- BIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需 要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器).
2. Java BIO工作机制
对BIO编程流程的梳理
3. 传统的BIO编程实例回顾
在传统的BIO(Blocking I/O)编程模型中,客户端(Client)和服务端(Server)之间的通信是基于同步阻塞方式进行的。 在这种模型下,服务端使用ServerSocket来绑定IP地址和监听端口,并启动监听。客户端则使用Socket来发起连接请求。
当客户端发起连接请求后,服务端接受连接并创建一个新的Socket与客户端进行通信。通信过程中,双方通过输入流和输出流进行数据的读取和写入。
在这种同步阻塞模型下,客户端和服务端是完全同步、完全耦合的关系。这意味着当客户端向服务端发送请求时,客户端会一直等待直到服务端响应完成;而服务端在处理客户端请求时也会一直阻塞,直到请求处理完成后才能继续处理下一个请求。当有大量的并发连接时,每个连接都需要独占一个线程来处理,导致资源消耗过高,无法支持高并发场景。
客户端案例如下
package com.zbbmeta.client;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
目标: Socket网络编程。
Java提供了一个包:java.net下的类都是用于网络通信。
Java提供了基于套接字(端口)Socket的网络通信模式,我们基于这种模式就可以直接实现TCP通信。
只要用Socket通信,那么就是基于TCP可靠传输通信。
功能1:客户端发送一个消息,服务端接口一个消息,通信结束!!
创建客户端对象:
(1)创建一个Socket的通信管道,请求与服务端的端口连接。
(2)从Socket管道中得到一个字节输出流。
(3)把字节流改装成自己需要的流进行数据的发送
创建服务端对象:
(1)注册端口
(2)开始等待接收客户端的连接,得到一个端到端的Socket管道
(3)从Socket管道中得到一个字节输入流。
(4)把字节输入流包装成自己需要的流进行数据的读取。
Socket的使用:
构造器:public Socket(String host, int port)
方法: public OutputStream getOutputStream():获取字节输出流
public InputStream getInputStream() :获取字节输入流
ServerSocket的使用:
构造器:public ServerSocket(int port)
小结:
通信是很严格的,对方怎么发你就怎么收,对方发多少你就只能收多少!!
*/
public class BioClient01 {
public static void main(String[] args) throws IOException {
System.out.println("==客户端的启动==");
// (1)创建一个Socket的通信管道,请求与服务端的端口连接。
Socket socket = new Socket("127.0.0.1",8899);
// (2)从Socket通信管道中得到一个字节输出流。
OutputStream os = socket.getOutputStream();
// (3)把字节流改装成自己需要的流进行数据的发送
PrintStream ps = new PrintStream(os);
// (4)开始发送消息
ps.println("我是客户端,我想约你吃小龙虾!!!");
ps.flush();
}
}
服务端案例如下
package com.zbbmeta.server;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class BioServer01 {
public static void main(String[] args) throws IOException {
System.out.println("==服务器的启动==");
// (1)注册端口
ServerSocket serverSocket = new ServerSocket(8899);
//(2)开始在这里暂停等待接收客户端的连接,得到一个端到端的Socket管道
Socket socket = serverSocket.accept();
//(3)从Socket管道中得到一个字节输入流。
InputStream is = socket.getInputStream();
//(4)把字节输入流包装成自己需要的流进行数据的读取。
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//(5)读取数据
String line ;
while((line = br.readLine())!=null){
System.out.println("服务端收到:"+line);
}
}
}
小结
- 在Java BIO中,确实存在服务端一直等待客户端消息的情况。如果客户端没有发送消息,服务端将一直阻塞在读取操作上,无法继续执行后续代码
- 服务端按行获取消息是一种常见的处理方式,即服务端通过BufferedReader逐行读取客户端发送的消息。因此,客户端也需要按行发送消息,以便服务端可以正确地解析和处理
- 面对大量并发连接时,每个连接都需要独占一个线程来处理,这会导致资源消耗过高,无法支持高并发场景