I/O模型的定义
什么是I/O模型呢? 简单来说就是说用什么样的通道进行数据的发送和接收。
在Java中,共支持3种网络编程IO模式:BIO,NIO,AIO
BIO
Demo Server
package com.artisan.iomodel.bio; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; /** * @author 小工匠 * @version 1.0 * @description: TODO * @date 2021/1/16 22:23 * @mark: show me the code , change the world */ public class SocketServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(7777); while (true) { System.out.println("等待client连接...."); //阻塞方法 Socket clientSocket = serverSocket.accept(); System.out.println("已收到客户端的连接....,开始处理"); handler(clientSocket); /*new Thread(new Runnable() { @Override public void run() { try { handler(clientSocket); } catch (IOException e) { e.printStackTrace(); } } }).start();*/ } } private static void handler(Socket clientSocket) throws IOException { byte[] bytes = new byte[1024]; System.out.println("准备读取客户端发送来的数据"); //接收客户端的数据,阻塞方法,没有数据可读时就阻塞 int read = clientSocket.getInputStream().read(bytes); System.out.println("读取ing"); if (read != -1) { System.out.println("接收到客户端的数据:" + new String(bytes, 0, read)); } // 向服务端发送数据 clientSocket.getOutputStream().write("HelloClient".getBytes()); // 缓冲区刷新 clientSocket.getOutputStream().flush(); } }
Demo Client
package com.artisan.iomodel.bio; import java.io.IOException; import java.net.Socket; /** * @author 小工匠 * @version 1.0 * @description: TODO * @date 2021/1/16 22:27 * @mark: show me the code , change the world */ public class SocketClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("localhost", 7777); //向服务端发送数据 socket.getOutputStream().write("HelloServer".getBytes()); socket.getOutputStream().flush(); System.out.println("向服务端发送数据结束"); byte[] bytes = new byte[1024]; //接收服务端回传的数据 socket.getInputStream().read(bytes); System.out.println("接收到服务端的数据:" + new String(bytes)); socket.close(); } }
Demo Run
启动 Server,
然后启动Client
同时看下Server的数据
我们用cmd工具来连一下 , telnet 127.0.0.1 7777
回车,输入 ctrl + ]
作为客户端发送消息
查看server是否收到
BIO 同步阻塞模型
通过上面的例子,可以看到 一个客户端连接对应一个处理线程
上面的线程模型 可以看到 只有一个main线程在处理,如果当前main线程没有处理完,后,后面的请求是无法被处理的 。
当然了我们上面的是一个线程的, 也可以改造为多线程 。
new Thread(new Runnable() { @Override public void run() { try { handler(clientSocket); } catch (IOException e) { e.printStackTrace(); } } }).start();
就变成了下面这种模式
小结
缺点显而易见
- read操作是阻塞操作,如果连接不做数据读写操作会导致线程阻塞,浪费资源
- 每个请求都需要开辟一个线程去处理,开辟过多的线程势必会导致服务器资源紧张。
BIO 方式适用于连接数目比较小且固定的架构, 这种方式对服务器资源要求比较高, 但程序简单易理解。