1 概要
- 本文次要探讨 BIO 模型下,客户端和服务端如何进行交互;
- 同时遗留一个问题,临时无解,待当前解决,如果有大神能指点迷津,不胜感激。
2 原理
BIO 顾名思义,Block IO;一旦数据没有筹备实现,那么就会阻塞;期待数据筹备实现,才会往下执行。
所以 socket 的连贯、读、写都会阻塞住。
2.2 长处
在晚期,这种模型也是很好用的。
2.3 毛病
BIO 模式下,为了减少服务端的并发,一个客户端申请往往单开一个线程,而不是占用服务端的主线程。即使是这种状况,服务端的并发量也是顾此失彼,因为一旦客户端不发送音讯了,服务端的一个线程也是阻塞,而不是敞开;也占用资源。
3 具体实现
3.0 代码实现逻辑
客户端发申请,服务端接管申请;服务端接管申请后,在发给客户端一个响应申请;以此往返;
3.1 应用原生的 InputStream
3.1.1 Server
public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(8899)) {Socket accept = serverSocket.accept();
while (true) {System.out.println("服务端 收到客户端的申请地址:" + accept.getInetAddress());
while (Objects.nonNull(accept)) {System.out.println(111);
InputStream in = accept.getInputStream();
byte[] bytes = new byte[1024];
int length = 0;
while ((length = in.read(bytes)) != -1) {System.out.println("msg from client :" + new String(bytes, 0, length));
}
System.out.println("server read msg over");
OutputStream outputStream = accept.getOutputStream();
String msg = "hello client, I am from Server";
outputStream.write(msg.getBytes(StandardCharsets.UTF_8));
outputStream.flush();}
}
} catch (Exception e) {e.printStackTrace();
}
}
3.1.2 Client
public static void main(String[] args) {try (Socket socket = new Socket("localhost", 8899)) {while (true) {OutputStream ois = socket.getOutputStream();
String hello = "hello server ,I am from Client;";
ois.write(hello.getBytes(StandardCharsets.UTF_8));
ois.flush();
System.out.println("client write msg over");
Thread.sleep(666);
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int length = 0;
while ((length = inputStream.read(bytes)) != -1) {System.out.println("msg from server:" + new String(bytes, 0, length));
}
}
} catch (Exception e) {e.printStackTrace();
}
}
3.1.3 论断
这种计划,会阻塞;通过打印堆栈信息能够看出,都是卡在 socketRead0()办法;即调用 inputstream.read(bytes)
的时候卡住;
即始终获取不到内容,所以始终卡主;纳闷点?
- 那应该通信几次再卡住才是,而不是一启动就卡主吧?
- 以后是找到了起因。但没找到解决办法;
- 猜想:以后是不是客服端和服务端共用一个 socket,只有有一个写、一个读?
3.2 将 InputStream 批改成 DataInputStream
3.2.1 Server
public static void main(String[] args) {try (ServerSocket serverSocket = new ServerSocket(8899)) {Socket accept = serverSocket.accept();
while (true) {System.out.println("以后连贯服务器的客户端地址:" + accept.getInetAddress());
DataInputStream dis = new DataInputStream(accept.getInputStream());
String clientMsg = dis.readUTF();
System.out.println("msg from client:" + clientMsg);
DataOutputStream dos = new DataOutputStream(accept.getOutputStream());
dos.writeUTF("hello client , I am from server ,msg received +" + clientMsg);
}
} catch (Exception e) {e.printStackTrace();
}
}
3.2.2 Client
public static void main(String[] args) {try (Socket socket = new Socket("localhost", 8899)) {DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while(true) {
String msg = "I am from client";
dos.writeUTF(msg);
String s = dis.readUTF();
System.out.println("msg from server:"+ s);
}
}catch (Exception e) {e.printStackTrace();
}
}
3.2.3
不会有阻塞;很奇怪; 单方信息打印很通顺;
3.3 应用 telnet 作为客户端进行发送音讯
- 应用 InputStream,如果没有音讯,会卡在 socketRead0(); 然而 telnet 客户端一旦输出内容,就会立刻往下走;
- 但应用 DataInputStream 会卡主,telnet 输出音讯 也会卡在 socketRead0()办法;
3.4 论断
暂无论断;
待问题解决