一、BIO(Blocking I/O)简介
- 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。
- Java中的BIO分为两种:
(1)、传统 BIO:一请求一应答
(2)、伪异步 IO:通过线程池固定线程的最大数量,防止资源的耗费。
BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中。
二、BIO代码实现
1、Server
/**
* 1、服务器端启动一个ServerSocket
* 2、客户端启动Socket对服务器端进行通信, 默认情况下服务器端需要对每一个客户端建立线程与之通讯
* 3、客户端发出请求后,先咨询服务器是否有线程响应,如果没有 则会等待,或者被拒绝
* 4、如果有响应,客户端会等待请求结束之后,再继续执行
*
*/
public class BioServer {
public static void main(String[] args) throws Exception {
// 使用线程池机制
// 1、创建一个线程池
// 2、如果有客户端连接,就创建一个线程与之通讯(单独写一个方法)
ExecutorService threadPool = Executors.newCachedThreadPool();
// 创建ServerSocket,监听一个端口
@SuppressWarnings("resource")
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器端启动了");
while (true) {
// 监听,等待客户端连接
final Socket socket = serverSocket.accept();
// 获取到客户端的ip和port
InetAddress inetAddress = socket.getInetAddress();
String address = inetAddress.getHostAddress();
int port = socket.getPort();
final String ipAddress = address + ":" + port;
System.out.println("连接到一个客户端:"+ipAddress);
// 创建一个线程,与之通讯
threadPool.execute(new Runnable() {
public void run() { // 重写run方法
// 可以和客户端进行通讯
handle(socket,ipAddress);
}
});
}
}
// 编写一个handle方法和客户端进行通讯
public static void handle(Socket socket,String ipAddress) {
try {
byte[] bytes = new byte[1024];
// 通过socket获得输入流
InputStream inputStream = socket.getInputStream();
// 循环读取客户端发送的数据
while (true) {
int read = inputStream.read(bytes);
if (read != -1) {
System.out.println(ipAddress + "发送的数据为:"
+ new String(bytes, 0, read)); // 输出数据
} else {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("关闭和client的连接");
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2、client
public class BioClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",6666);
OutputStream outputStream = socket.getOutputStream();
String send = "hello world";
byte[] bytes = send.getBytes();
outputStream.write(bytes);
socket.close();
outputStream.close();
}
}
效果如下:
3、telnet测试
(1)、连接Server
telnet 127.0.0.1 6666
(2)、发送字符
(3)、效果如下