BIO即 Blocking IO,是同步阻塞的编程方式,BIO 编程方式通常是在JDK1.4 版本之前常用的编程方式。
BIO服务端通信模型图:
图源网络,侵删
采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成之后,通过输出流返回应答给客户端,线程销毁。这就是典型的一请求一应答通信模型。
一、BIO服务端编程
- 步骤:
- 创建ServerSocket实例
- 绑定占用端口
- 通过accept()方法监听并等待客户端的连接
- 如果有客户端连接则获得socket实例
- 通过socket实例进行读写操作
- 关闭资源和socket
- 代码展示:
public class BIOServer {
public static void main(String[] args) {
try {
//1.创建ServerSocket实例
ServerSocket serverSocket = new ServerSocket();
//2.绑定占用端口
serverSocket.bind(new InetSocketAddress(6666));
System.out.println("服务端已开启,等待客户端连接!!!");
//3.通过accept()方法监听并等待客户端的连接,如果有客户端连接则获得socket实例
Socket socket = serverSocket.accept();
System.out.println("有新用户连接...."+socket);
//4.通过socket实例进行读写操作
//进行通信
//读操作流
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//写操作流
OutputStream outputStream = socket.getOutputStream();
String message = null;
//读操作
while ((message = reader.readLine()) != null){
System.out.println("收到客户端发送的数据"+message);
//给客户端回复消息
outputStream.write(("服务端已收到数据"+message).getBytes());
//刷新
outputStream.flush();
}
//5.关闭资源和socket
reader.close();
serverSocket.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、BIO客户端编程
- 步骤:
- 创建socket实例
- 通过connect()连接服务器
- 进行读写操作
- 关闭资源
- 代码展示:
public class BIOClient {
public static void main(String[] args) throws IOException {
//1.创建socket实例
Socket socket = new Socket();
//2.通过connect()连接服务器
InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",6666);
socket.connect(socketAddress);
System.out.println("客户端成功连接服务器");
//3.进行读写操作
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
//从键盘读取数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要发送的消息:");
while (scanner.hasNext()){
//接收键盘输入
String string = scanner.nextLine();
//发送操作
outputStream.write((string+"\n").getBytes());
outputStream.flush();
//接收服务端返回
byte[] bytes = new byte[1024];
int read = inputStream.read(bytes);
String recv = new String(bytes,0,read);
System.out.println("recv:"+recv);
System.out.println("请输入要发送的消息:");
if ("exit".equals(string)){
break;
}
}
System.out.println("客户端关闭了");
//4.关闭资源
socket.close();
}
}
在服务端和客户端编程中, accept()、connect()、read()、write()方法都是阻塞的
三 、BIO劣势
每当有一个新客户端请求接入,服务端都会创建一个新的线程,无法满足高性能、高并发场景。