实例说明
- 使用 BIO 模型编写一个服务器端,监听 6666 端口,当有客户端连接时,就启动一个线程与之通讯。
- 要求使用线程池机制改善,可以连接多个客户端。
- 服务器端可以接收客户端发送的数据(telnet 方式即可)。
服务器端代码
```java package com.xiaomeng.netty.learnnetty.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 xiaomeng
@date 2021-12-11 */ public class BIOServer {
public static void main(String[] args) throws IOException {
//思路
//1、创建一个连接池
//2、如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)
//创建连接池
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//ServerSocket 是服务器端的,等待客户端的请求,监听6666端口
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器启动了...");
//服务器端随时待命
while (true){
System.out.println("线程信息id ="+ Thread.currentThread().getId() + ",name = "+Thread.currentThread().getName());
//监听,等待客户端连接
System.out.println("等待连接...");
final Socket accept = serverSocket.accept();
System.out.println("连接到一个客户端");
//创建一个线程,与之通讯(单独写一个方法)
newCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
//可以和客户端通信
handler(accept);
}
});
}
}
/*
- 更客户端通信
@param accept */ private static void handler(Socket accept) { try {
System.out.println("线程信息id ="+ Thread.currentThread().getId() + ",name = "+Thread.currentThread().getName());
//获取输入流,读取客户端的数据
InputStream inputStream = accept.getInputStream();
byte[] bytes = new byte[1024];
//循环读取客户端发送的数据
while (true){
System.out.println("线程信息id ="+ Thread.currentThread().getId() + ",name = "+Thread.currentThread().getName());
int read = inputStream.read(bytes);
if(read != -1){
System.out.println(new String(bytes,0,read));
}else{
break;
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭客户端的连接
System.out.println("关闭客户端连接");
try {
accept.close();
}catch (Exception e){
e.printStackTrace();
}
}
} }
测试
创建telnet当客户端发送数据
1、系统启用telnet功能
1)打开控制面板-程序和功能
2)启用或关闭 windows 功能
3)勾选TelNet客户端
如果没有启用功能,会报错:telnet不是内部命令
2、客户端连接服务器 ip 和端口
新建一个cmd窗口,然后输入 telnet 127.0.0.1 6666,回车
3、按 ctrl+] 回显输入内容
4、输入 send+ 发送的内容,回车
5、服务器端控制台 收到客户端发送内容,并且打印出了线程
6、再创建一个客户端,发送内容,服务端查看发送内容和 线程
总结
- Java BIO 就是传统的 Java I/O 编程,其相关的类和接口在 java.io。
- BIO(BlockingI/O):同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程池机制改善(实现多个客户连接服务器)
- 每个请求都需要创建独立的线程,与对应的客户端进行数据 Read,业务处理,数据 Write。
- 当并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。
- 连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费。