quick_start
入门代码
当前代码缺点:代码获取完一次客户端发送的数据,就结束了
public class BioServer {
public static void main(String[] args) throws IOException {
//创建服务端,绑定8000端口
ServerSocket serverSocket = new ServerSocket(8000);
//获取客户端连接
Socket clientSocket = serverSocket.accept();
byte[] bytes = new byte[1024];
//读取客户端发送的数据
int read = clientSocket.getInputStream().read(bytes);
if (read != -1) {
System.out.println("收到客户端的数据:" + new String(bytes, 0, read));
}
}
}
优化代码v1.0
优化方案:循环获取客户端连接
优化后缺点:一个客户端连接只能发送一次
public class BioServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
Socket clientSocket = serverSocket.accept();
byte[] bytes = new byte[1024];
int read = clientSocket.getInputStream().read(bytes);
if (read != -1) {
System.out.println("收到客户端的数据:" + new String(bytes, 0, read));
}
}
}
}
优化代码v1.1
优化方案:循环获取当前客户端连接发送的数据
优化后缺点:只能接收一个客户端连接发送的数据
public class BioServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
Socket clientSocket = serverSocket.accept();
byte[] bytes = new byte[1024];
while (true) {
int read = clientSocket.getInputStream().read(bytes);
if (read != -1) {
System.out.println("收到客户端的数据:" + new String(bytes, 0, read));
}
}
}
}
}
优化代码v1.2
优化方案:每个客户端发送的数据用单独线程接收
优化后缺点:连接越多,线程越多
public class BioServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
Socket clientSocket = serverSocket.accept();
new Thread(() -> {
byte[] bytes = new byte[1024];
while (true) {
int read = 0;
try {
read = clientSocket.getInputStream().read(bytes);
if (read != -1) {
System.out.println("收到客户端的数据:" + new String(bytes, 0, read));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
终版代码
public class BioServer {
private static ThreadPoolExecutor threadPoolExecutor;
static {
// 创建线程池
threadPoolExecutor = new ThreadPoolExecutor(200, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
}
public static void main(String[] args) throws IOException {
// 创建服务端,绑定8000端口
ServerSocket serverSocket = new ServerSocket(8000);
while (true) {
// 获取客户端连接
Socket clientSocket = serverSocket.accept();
// 使用线程池监听连接发送的数据
threadPoolExecutor.submit(() -> {
byte[] bytes = new byte[1024];
while (true) {
int read = 0;
try {
// 读取客户端发送的数据
read = clientSocket.getInputStream().read(bytes);
if (read != -1) {
System.out.println("收到客户端的数据:" + new String(bytes, 0, read));
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}
阻塞的含义
- accept()会阻塞,直到有新连接连接
- read(bytes)会阻塞,直到用户发送数据
BIO缺点
- 连接越多,占用的线程越多
- 客户端连接多,但发送数据的客户端少时,并且这些线程把线程池占满,新的连接都将阻塞,程序将毫无意义