IO模型
IO模型就是说用什么样的通道进行数据的发送和接收,Java共支持3种网络编程IO模式:BIO,NIO,AIO
BIO(Blocking IO )
同步阻塞模型,一个客户端连接对应一个处理线程
BIO代码示例:
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Handler;
public class SocketServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9000);
while (true){
System.out.println("等待连接");
//阻塞连接
Socket clientSocket = serverSocket.accept();
System.out.println("有客户端连接。。。");
// handle(clientSocket);
new Thread(new Runnable() {
@Override
public void run() {
try {
handle(clientSocket);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
public static void handle(Socket clientSocket) throws Exception{
byte[] bytes = new byte[1024];
System.out.println("准备read。。");
//接收客户端的数据,阻塞方法,没有数据可读时就阻塞
int read = clientSocket.getInputStream().read(bytes);
System.out.println("read 完毕。");
if (read !=-1){
System.out.println("接收到客户端数据:" + new String(bytes,0,read));
}
clientSocket.getOutputStream().write("helloClient".getBytes());
clientSocket.getOutputStream().flush();
}
}
//客户端代码
import java.io.IOException;
import java.net.Socket;
public class SocketClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 9000);
//向服务端发送数据
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();
}
}
缺点:
从上面的代码我们可以看出来,BIO代码中连接事件和读写数据事件都是阻塞的,所以这种模式的缺点非常的明显
1、如果我们连接完成以后,不做读写数据操作会导致线程阻塞,浪费资源
2、如果没来一个连接我们都需要启动一个线程处理,那么会导致服务器线程太多,压力太大,比如C10K;
应用场景:
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,但是程序比较简单。
NIO(Non Blocking IO)
同步非阻塞模型,服务器实现模式为一个线程可以处理多个请求连接,客户端发送的连接请求都会注册到多路复用器(selector)上,多路复用器轮询到连接有IO请求就进行处理,JDK1.4开始引入。
//没有引入多路复用器的代码
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.chan