Java IO、NIO、AIO

IO、NIO、AIO

Socket

在应用程序中通常使用套接字来向网络发出请求或者应答网络请求。

Socket(套接字):用于唯一标识网络上的某台主机上的某个进程(服务),Socket就是IP:Port的形式,一个IP地址和一个端口号来标识。

Java中Socket和ServerSocket类库位于Java.net包中,ServerSocket用于服务器端,Socket则在建立网络链接时使用,也就是客户端,在连接完成后应用程序两端都会产生Socket实例。注意:虽然有客户端和服务端的概念,但是对于网络连接来说,套接字是平等的

建立网络连接:

  1. 服务器监听:服务端打开端口,用于监听连接请求。
  2. 客户端请求:客户端使用套接字来请求连接。
  3. 服务端确认:监听到连接请求后,响应客户端的请求,并建立一个新的进程用于响应,然后将服务端的套接字发送回客户端。
  4. 一旦客户端确认了,就建立好连接,双方开始通信。客户端仍然处于监听状态。

网络编程的基于模型Client/Server模型,三次握手,基于TCP的连接。

IO

直接使用Socket建立连接,进行通信的方式就是BIO(阻塞式IO)在建立TCP响应的时候,对于服务端端口是阻塞的。当有一个客户端进行访问时,其他的客户端是不能访问的。

优化方案:服务端使用线程池管理,伪异步。但由于使用的是阻塞队列,所以是伪异步的。

public class Server {
final static int PORT = 8765;
public static void main(String[] args) {
	ServerSocket server = null;
	BufferedReader in = null;
	PrintWriter out = null;
	try {
	server = new ServerSocket(PORT);
	System.out.println("server start");
	Socket socket = null;
	HandlerExecutorPool executorPool = new 		HandlerExecutorPool(50, 1000);
	while(true){
		socket = server.accept();
		//使用线程池进行操作实现异步
		executorPool.execute(new ServerHandler(socket));
		}
		} catch (Exception e) {
			e.printStackTrace();
		} 

NIO

NIO有两种说法new IO和Not—block IO。习惯于非阻塞IO。注意NIO只是非阻塞但不是异步的。

本质就是避免了TCP连接的3次握手操作,减少连接的开销。

核心是通道和多路复用器:

通道:双向的通信方式,具有读写的能力,同时具有状态位。

多路复用器:也就是seletor。提供轮询管理通道的能力。所有通道都由selector管理。每一个在复用器上注册了的管道都会被分配一个key用作标识,复用器也会通过key去找到相应的管道。

在这里插入图片描述

每个管道具有的状态码:

SelectionKey.OP_CONNECT 连接状态

SelectionKey.OP_ACCEPT 阻塞状态

SelectionKey.OP_READ 可读状态

SelectionKey.OP_WRITE 可写状态

步骤:

创建NIO服务器的主要步骤
    (1)打开ServerSocketChannel,监听客户端连接
    (2)绑定监听端口,设置连接为非阻塞模式
    (3)创建Reactor线程,创建多路复用器并启动线程
     (4)将ServerSocketChannel注册到Reactor线程中的Selector上,监听ACCEPT事件
     (5)Selector轮询准备就绪的key
     (6)Selector监听到新的客户端接入,处理新的接入请求,完成TCP三次握手,简历物理链路
     (7)设置客户端链路为非阻塞模式
     (8)将新接入的客户端连接注册到Reactor线程的Selector上,监听读操作,读取客户端发送的网络消息
     (9)异步读取客户端消息到缓冲区
     (10)对Buffer编解码,处理半包消息,将解码成功的消息封装成Task
     (11)将应答消息编码为Buffer,调用SocketChannel的write将消息异步发送给客户端

AIO

AIO编程,在NIO基础上引入了异步通道的概念,提供异步文件和异步套接字通道的实现,从而在真正意义上实现了异步非阻塞。核心是AsynchronousServerScoketChannel和AsynchronousScoketChanel

核心:

//客户端:
executorService = Executors.newCachedThreadPool();

//创建线程组

threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 1);

//创建服务器通道

assc = AsynchronousServerSocketChannel.open(threadGroup);

//进行绑定

assc.bind(new InetSocketAddress(port));

System.out.println("server start , port : " + port);

//进行阻塞

assc.accept(this, new ServerCompletionHandler());

//一直阻塞 不让服务器停止

Thread.sleep(Integer.MAX_VALUE);

//handler
public void completed(AsynchronousSocketChannel asc, Server attachment) {

//当有下一个客户端接入的时候 直接调用Server的accept方法,这样反复执行下去,保证多个客户端都可以阻塞(没有递归上限),1.7以后AIO才实现了异步非阻塞

attachment.assc.accept(attachment, this);

read(asc);

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章