VI . BIO 实例
1 . BIO 示例 :
① 服务器端 : 编写服务器端 , 监听 8888 端口 , 阻塞等待客户端连接 , 连接成功后 , 创建线程 , 线程中阻塞等待客户端发送请求数据 ;
② 客户端 : 编写一个客户端 , 请求服务器的 8888 端口号 , 客户端发送 “Hello World” 字符串给服务器端 ;
③ Telnet 客户端 : 使用 Telnet 客户端向上述服务器端 8888 端口 发送 “Hello World” 字符串请求 ;
2 . 服务器代码示例 :
package kim.hsl.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; public class TCPServer { public static void main(String[] args) { try { //创建线程池 ExecutorService threadPool = Executors.newCachedThreadPool(); //创建服务器套接字 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器启动,监听 8888 端口"); while (true){ //阻塞, 等待客户端连接请求 ( 此处是第一个阻塞点 ) Socket socket = serverSocket.accept(); System.out.println("客户端连接成功"); //线程池启动线程 threadPool.execute(new ClientRquest(socket)); } } catch (IOException e) { e.printStackTrace(); } } /** * 与客户端交互类 */ static class ClientRquest implements Runnable { private Socket socket; public ClientRquest(Socket socket) { this.socket = socket; } @Override public void run() { try { clientRequest(); } catch (IOException e) { e.printStackTrace(); } finally { //最终要将 Socket 关闭, 如果出异常继续捕获 try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public void clientRequest() throws IOException { //获取输入流, 读取客户端写入的信息 byte[] buffer = new byte[1024]; InputStream is = socket.getInputStream(); System.out.println("等到客户端请求"); //此处会阻塞等待客户端的请求 ( 此处是第二个阻塞点 ) int count = is.read(buffer); String request = new String(buffer, 0, count); System.out.println("客户端请求到达 : " + request); } } }
3 . 客户端代码示例 :
package kim.hsl.bio;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) {
try {
Socket socket = new Socket();
InetSocketAddress inetSocketAddress =
new InetSocketAddress(
Inet4Address.getLocalHost(), //本机IP地址
8888 //端口号
);
System.out.println("客户端开始连接 ...");
//此处会阻塞等待连接成功
socket.connect(inetSocketAddress);
System.out.println("客户端连接成功");
//连接成功后, 开始执行后续操作
socket.getOutputStream().write("Hello World".getBytes());
System.out.println("客户端写出 Hello World 成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
4 . 执行结果 :
① 启动服务器 :
② 启动客户端 :
③ 使用 Telnet 客户端测试 localhost 8888 端口 :
建立连接 : 在命令行工具中 , 使用 telnet localhost 8888 连接本机的 8888 端口 ;
连接成功后 , 按下 Ctrl + ] 快捷键 , 进入 Telnet 命令行 , 输入 send Hello World 命令 , 向本机的 8888 端口发送 Hello World 字符串 ;
服务器端显示 :
VII . BIO 模型实例分析
BIO 模型实例分析 : 针对上述 BIO 实例 , 从性能 , 线程个数 , 阻塞 等角度分析 BIO 模型 ;
① 线程维护个数 : 在服务器端 , 需要针对每个客户端连接都创建一个线程 , 有多少连接 , 就需要有多少线程 ;
② 性能分析 : 如果客户端数量很多 , 那么大量客户端同时连接 , 其并发数量很大 , 对系统的资源占用较高 ;
③ 阻塞分析 : BIO 模型中 , 服务器端有两处阻塞 , 一个是等待客户端连接 , 一个是连接后 , 等待客户端发出请求数据 , 后者的阻塞等待完全就是对资源的浪费 , 没有数据交互 , 一直占用资源 ;