实例说明
- 使用 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() {@Overridepublic 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 操作上,造成线程资源浪费。
