介绍
BIO(blocking I/O)就是传统的 java io 编程,BIO是同步阻塞模型,服务器端实现模式为一个连接只有一个线程处理,如果这个连接不做任何事情,会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)。
BIO模型适用于连接数较小且固定的架构,这种方式对服务器资源要求比较高,JDK1.4以前的唯一选择,优点是程序简单易理解。
工作原理
1、服务端启动一个ServerSocket
2、客户端启动Socket对服务器进行通讯,默认情况下服务器端需要对每个客户端建立一个线程与之通讯
3、客户端发出请求后,先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝。
4、如果有响应,客户端线程会等待请求结束后,再继续执行
代码演示
服务端
package com.tk.netty.bio;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* BIO模型
*
* @author taoke
* @date 2022/5/6
*/
public class BIOServer {
public static void main(String[] args) throws Exception {
//1.创建一个线程池
//2.如果有客户端连接,就创建一个线程,与之通讯
ExecutorService threadPool = Executors.newCachedThreadPool();
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器启动了!");
while (true) {
System.out.println("连接中。。。");
//监听,等待客户端连接
final Socket socket = serverSocket.accept();
System.out.println("连接到一个客户端");
//创建一个线程,与之通讯
threadPool.execute(() -> handler(socket));
}
}
/**
* 和客户端进行通讯
*
* @param socket 套接字
*/
public static void handler(Socket socket) {
try {
byte[] bytes = new byte[1024];
//通过socket获取输入流
InputStream inputStream = socket.getInputStream();
System.out.println("线程id=" + Thread.currentThread().getId() + ", 线程名字=" + Thread.currentThread().getName());
//循环读取客户端发送的数据
int len;
while ((len = inputStream.read(bytes)) != -1) {
System.out.println(Thread.currentThread().getName() + ": " + new String(bytes, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果
1、服务端启动,等待客户端连接
2、cmd telnet连接服务端
客户端 连接成功,按 ctrl+]
服务端连接成功,第二个连接中是因为,服务端accept()监听阻塞,当有客户端进来时,会创建一个子进程,然后重新回到主线程。
3、客户端发送消息与服务端进行通讯
服务端收到消息