携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第43天,点击查看活动详情 >>
使用java模拟BIO模型
今天我们来学习BIO模型,在学习的过程中,我们会通过具体的代码例子来来讲解。
什么是BIO模型
BIO模式,又叫同步阻塞模型(blocking i/o),这是一种传统的IO模型,服务器的实现模式为一个连接一个线程,即对于每一个客户端的连接,服务器都会开启一个线程来处理它。
当然啦,因为这是高度专一了,所以如果客户端到来的连接不做任何事情,那么就会给服务器造成额外的线程开销。
BIO的使用场景
BIO模型是比较适合于连接数较少的并且固定的架构中的,因为这种方式对服务器资源要求比较高,在并发场景中受限较大。
用Java代码实现一个BIO模型的服务器:
在真正展示代码之前,我们先来说明一下,这里对服务器的要求:
- 服务器中需要启动一个ServerSocket
- 客户端对服务器进行通信,默认是一个连接对应服务器中的一个线程
- 在客户端的请求被发出后,若服务器有线程响应,则返回;若没有线程响应,则会等待,或者拒接
- 如果有响应,客户端线程会等待请求结束后,在继续执行
了解了服务器的需求之后,那么我们就开始动手自己写一个:
简易的BIO服务器,主函数代码如下:
public static void main(String[] args) throws Exception {
// 创建线程池
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
ServerSocket serverSocket = new ServerSocket(666);
System.out.println("服务器启动。。。");
while (true) {
System.out.println("before connect : 线程id = " + Thread.currentThread().getId() + "\t线程名 = " + Thread.currentThread().getName());
System.out.println("waiting for connect...");
final Socket acceptSocket = serverSocket.accept();
System.out.println("连接到一个客户端");
// 创建线程
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
handle(acceptSocket);
}
});
}
}
在服务器开启之后,那么剩下的就是等待客户端的连接和读取数据了,下面我们来学习一下相关的方法实现:
public static void handle(Socket acceptSocket) {
try {
System.out.println("线程id = " + Thread.currentThread().getId() + "\t线程名 = " + Thread.currentThread().getName());
InputStream inputStream = acceptSocket.getInputStream();
byte[] bytes = new byte[1024];
// 循环读取数据到 bytes
while (true) {
System.out.println("reading...");
int read = inputStream.read(bytes);
if (read != -1) {
System.out.println("线程id = " + Thread.currentThread().getId() + "\t线程名 = " + Thread.currentThread().getName());
System.out.println(new String(bytes, 0, read));
} else {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("断开连接");
try {
acceptSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
经过了上面两步我们已经完成了一个简易的BIO服务器了,在每个客户端连接到来的时候,服务器都会开启一个线程对其进行处理。
总结:
BIO模型是一种传统的IO模型,在一些固定架构且较小的场景下,更实用;因为如果是在高并发场景下的话,它承受不了那么大的线程开销。