2023-08-28 11:43

C/S架构网络BIO、NIO和AIO的区别

码自答

JavaEE

(391)

(0)

收藏

  • BIO同步阻塞

    服务器端创建ServerSocket对象,客户端创建Socket对象来连接服务器进行通信,服务器端需要对每个请求建线程。客户端和服务器端的IO流是阻塞的。客户端的IO流,在服务器端将返回值传输回来之前,都是处于阻塞的状态,服务器和客户端一直占用连接。

  • NIO同步非阻塞

    NIO解决了阻塞问题,不是每个连接对应一个线程,是一个有效的请求对应一个处理线程,连接公用线程。

    NIO中间的三个角色

    • SocketChannel

      类似BIO中间的Socket,用于建立连接和传输数据,可以被多个线程公用。

    • Buffer

      就是计算内存中间一块区域,通过Buffer实现数据的读写操作

    • Selector

      监听SocketChannel。实现非阻塞

      代码实现:

      NIOServer

    • package com.wanmait.nio;
      
      import java.io.IOException;
      import java.net.InetSocketAddress;
      import java.nio.ByteBuffer;
      import java.nio.channels.SelectionKey;
      import java.nio.channels.Selector;
      import java.nio.channels.ServerSocketChannel;
      import java.nio.channels.SocketChannel;
      import java.util.Set;
      
      public class TestServer {
      	public static void main(String[] args) {
      		try {
      			System.out.println("服务器");
      			
      			Selector selector = Selector.open();
      			
      			ServerSocketChannel serverChannel = ServerSocketChannel.open();
      			
      			serverChannel.configureBlocking(false);//设置为非阻塞模式
      			
      			serverChannel.socket().bind(new InetSocketAddress(50000),60000);
      			//设置监听的端口  50000 ~ 60000
      			
      			serverChannel.register(selector, SelectionKey.OP_ACCEPT);
      			//ServerSocketChanner注册到Selector 有Selector监听
      			
      			new Thread() {
      				public void run()
      				{
      					while(true)
      					{
      						try {
      							selector.select();
      							
      							Set<SelectionKey> selectionKeys = selector.selectedKeys();
      							
      							for(SelectionKey selectionKey:selectionKeys)
      							{
      								if(selectionKey.isValid())//判断key是否有效
      								{
      									ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel();
      									//建立连接
      									
      									SocketChannel client = server.accept();
      									//获得客户通道
      									
      									client.configureBlocking(true);
      									//设置成为阻塞
      									
      									ByteBuffer receivebuffer = ByteBuffer.allocate(1024);
      									
      									int count = client.read(receivebuffer);
      									//读取数据
      									
      									if(count>0)
      									{
      										receivebuffer.flip();
      										
      										byte[] bytes = new byte[receivebuffer.remaining()];
      										receivebuffer.get(bytes);
      										
      										String body = new String(bytes,"utf-8");
      										System.out.println(body);
      									}
      								}
      							}
      						} catch (IOException e) {
      							// TODO Auto-generated catch block
      							e.printStackTrace();
      						}
      					}
      				}
      			}.start();
      			
      		} catch (IOException e) {
      			// TODO Auto-generated catch block
      			e.printStackTrace();
      		}
      	}
      }


        NIOClient:

package com.wanmait.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class TestClient {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			SocketChannel socketChannel = SocketChannel.open();
		
			boolean flag = socketChannel.connect(new InetSocketAddress("127.0.0.1",50000));
			
			if(flag)
			{
				ByteBuffer sendbuffer = ByteBuffer.allocate(1024);
				
				sendbuffer.put("wanmait".getBytes());
				
				sendbuffer.flip();
				
				socketChannel.write(sendbuffer);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}



  • AIO异步非阻塞

    进行读写操作时,调用API的read和write方法。将可读的数据传入read方法,并通知程序读。

    AIO服务器代码:


  • package com.wanmait.aio;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.AsynchronousServerSocketChannel;
    import java.nio.channels.AsynchronousSocketChannel;
    import java.nio.channels.CompletionHandler;
    import java.nio.charset.Charset;
    import java.util.concurrent.TimeUnit;
    
    public class Server {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try {
    			ByteBuffer buffer = ByteBuffer.allocate(8);
    			
    			AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(50000));
    			
    			//读取数据
    			CompletionHandler<Integer,Object> completionData = new CompletionHandler<>() {
    
    				@Override
    				public void completed(Integer result, Object attachment) {
    					// TODO Auto-generated method stub
    					if(result!=-1)
    					{
    						buffer.flip();
    						System.out.println(Charset.forName("utf-8").decode(buffer));
    					}
    				}
    
    				@Override
    				public void failed(Throwable exc, Object attachment) {
    					// TODO Auto-generated method stub
    					exc.printStackTrace();
    				}
    				
    			};
    			
    			
    			//获得客户端的连接
    			CompletionHandler<AsynchronousSocketChannel,Object> completionClient = new CompletionHandler<>() {
    
    				@Override
    				public void completed(AsynchronousSocketChannel acceptChannel, Object attachment) {
    					// TODO Auto-generated method stub
    					acceptChannel.read(buffer,10L,TimeUnit.SECONDS,null,completionData);	
    				}
    
    				@Override
    				public void failed(Throwable exc, Object attachment) {
    					// TODO Auto-generated method stub
    					exc.printStackTrace();
    				}
    				
    			};
    			
    			server.accept(null,completionClient);
    			
    			Thread.sleep(5000);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		
    		
    	}
    
    }


AIO客户端代码:

package com.wanmait.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.ExecutionException;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
			
			client.connect(new InetSocketAddress("127.0.0.1",50000)).get();
			//连接服务器
			
			client.write(ByteBuffer.wrap("wanmait".getBytes()));
			//相服务器发送数据
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


0条评论

点击登录参与评论