Java BIO 基本使用
- 简介
1) Java BIO 就是传统的java io 编程,其相关的类和接口在 java.io
2) BIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,
如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)。
3) BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,程序简单易理解
-
工作原理图
-
工作流程
1) 服务器端启动一个ServerSocket
2) 客户端启动Socket对服务器进行通信,默认情况下服务器端需要对每个客户 建立一个线程与之通讯
3) 客户端发出请求后, 先咨询服务器是否有线程响应,如果没有则会等待,或者被拒绝
4) 如果有响应,客户端线程会等待请求结束后,在继续执行
- 代码实现步骤
1) 使用BIO模型编写一个服务器端,监听6666端口,当有客户端连接时,就启动一个线程与之通讯。
2) 要求使用线程池机制改善,可以连接多个客户端
3) 服务器端可以接收客户端发送的数据(telnet 方式)
- 新建1个gradle项目
- 编写如下代码
public class BIOServer {
public static void main(String[] args) throws Exception {
//线程池机制
//思路
//1. 创建一个线程池
//2. 如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器启动了");
while (true) {
System.out.println("线程信息id = " + Thread.currentThread().getId() + "名字 = " + Thread.currentThread().getName());
//监听,等待客户端连接
System.out.println("等待连接....");
final Socket socket = serverSocket.accept();
System.out.println("连接到一个客户端");
//就创建一个线程,与之通讯(单独写一个方法),
// 执行线程并不会阻塞,不需要等execute执行完就进入while下一次循环
newCachedThreadPool.execute(new Runnable() {
public void run() {//我们重写
//可以和客户端通讯
handler(socket);
}
});
}
}
//编写一个handler方法,和客户端通讯
public static void handler(Socket socket) {
try {
System.out.println("正在与线程信息id = " + Thread.currentThread().getId() + "名字 = " + Thread.currentThread().getName()+ "通信。。");
byte[] bytes = new byte[1024];
//通过socket获取输入流
InputStream inputStream = socket.getInputStream();
//循环的读取客户端发送的数据
while (true) {
System.out.println("read....");
//
int readLen = inputStream.read(bytes);
if (readLen != -1) {
System.out.println("线程" + Thread.currentThread().getId() + ":" +new String(bytes, 0, readLen));//输出客户端发送的数据
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("关闭和client的连接");
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 启动参考
# 配置build.gradle
plugins {
id 'application'
}
apply plugin :"java"
ext {
javaMainClass ="com.ychen.netty.bio.BIOServer"
}
application {
mainClassName = javaMainClass
}
task runWithJavaExec(type: JavaExec) {
group ="Execution"
description ="Run the main class with JavaExecTask"
classpath = sourceSets.main.runtimeClasspath
main = javaMainClass
}
-
执行任务
-
连接
# 打开cmd
telnet 127.0.0.1 6666
# 按住ctrl + ]
# 发送消息
send [msg]
- 查看控制台