什么是BIO
BIO编程方式通常是在JDK1.4版本之前常用的编程方式。编程实现过程为:首先在服务端启动一个ServerSocket来监听网络请求,客户端启动Socket发起网络请求,默认情况下ServerSocket回建立一个线程来处理此请求,如果服务端没有线程可用,客户端则会阻塞等待或遭到拒绝。
且建立好的连接,在通讯过程中,是同步的。在并发处理效率上比较低。大致结构如下:
同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
BIO能干嘛
在通讯中,以往都是使用BIO模型去进行通信系统设计
BIO通讯模型.png
如图中,一个服务端可以连接多个客户端,但是接入一个客户端,服务端都需要用一个线程维持着客户端与服务端的连接。如果客户端数量很多,那么服务端也需要对应的线程数量与之连接。##如何使用BIO模型
简单的演示:
一对一
服务端代码:
/**
* @Auther:
* @Date: 2021/7/9 15:27
* @Description:
*/
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("服务器启动.....");
// 1.定义一个serverSocket,并定义端口是 9999
ServerSocket ss = new ServerSocket(9999);
// 2.监听k客户端的socket请求
Socket socket = ss.accept();
// 3.从客户端传来的socket里面获取到流
InputStream is = socket.getInputStream();
// 4.将字节输入流包装成一个缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while((msg = br.readLine())!=null){
System.out.println("服务端接受到信息:" + msg);
}
}
}
客户端代码:
/**
* @Auther:
* @Date: 2021/7/9 15:27
* @Description:
*/
public class Client {
public static void main(String[] args) throws IOException {
// 1.创建socket将对象请求服务端的链接
Socket socket = new Socket("127.0.0.1",9999);
// 2.从socket对象中获取一个字符输出流
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner scanner = new Scanner(System.in);
while(true){
System.out.print("请说:");
String msg = scanner.nextLine();
ps.println(msg);
ps.flush();
}
}
}
运行一下(先启动服务端,再启动客户端)
客户端输入:
请说:哈喽
请说:
服务端接收:
服务器启动.....
服务端接受到信息:哈喽
一对多(使用线程实现)
服务端代码
/**
* @Auther:
* @Date: 2021/7/9 15:27
* @Description:
*/
public class Server {
public static void main(String[] args) throws IOException {
// 1.定义一个serverSocket,并定义端口是 9999
ServerSocket ss = new ServerSocket(9999);
while(true){
// 2.监听k客户端的socket请求
Socket socket = ss.accept();
new SocketThread(socket).start();
}
}
}
socket线程类
/**
* @Auther:
* @Date: 2021/7/9 15:55
* @Description:
*/
public class SocketThread extends Thread{
private Socket socket;
public SocketThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 1.从客户端传来的socket里面获取到流
InputStream is = socket.getInputStream();
// 2.将字节输入流包装成一个缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while((msg = br.readLine())!=null){
System.out.println("服务端接受到信息:"+msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端代码
/**
* @Auther:
* @Date: 2021/7/9 15:27
* @Description:
*/
public class Client {
public static void main(String[] args) throws IOException {
// 1.创建socket将对象请求服务端的链接
Socket socket = new Socket("127.0.0.1",9999);
// 2.从socket对象中获取一个字符输出流
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner scanner = new Scanner(System.in);
while(true){
System.out.print("请说:");
String msg = scanner.nextLine();
ps.println(msg);
// 推送发送内容给服务端
ps.flush();
}
}
}
启动设置,允许并行启动某个程序
image.png
然后测试一下,分别从两个客户端发送信息服务端都会接收到,这时候启用的是两个线程,每个socket线程对象都对应一个服务端的链接。
网友评论