• 高性能网络编程之IO和NIO阻塞分析


    一、内容

    1、阻塞和非阻塞是什么?

    2、传统IO模型,他存在哪些阻塞点

    3、NIO模型

    4、对比总结

    1、阻塞和非阻塞是什么?

    阻塞:做某件事情,直到完成,除非超时,如果没有完成,继续等待。

    非阻塞:做一件事情,尝试着做,如果说不能做完,就不做了。意思就是直接返回,如果能做完,就做。

    2、传统IO模型,他存在哪些阻塞点

    1) 传统IO:Socket编程  参考:Android 网络编程 Socket

    2) 阻塞点:

      1> Socket socket = serverSocket.accept();

      2> int data = is.read(b);

    缺点:如下图的,

    客户: socket

    大门: ServerSocket(port)

    服务器: Thread

    每个服务员服务一个客户,高并发下会出现很多线程。

    优点:

    2) NIO

    增加了一个重要的角色(Selector),主要负责调度和监控客户端和服务端(调度器)

    由阻塞方式改成了非阻塞(non-blocking)

     阻塞点

    this.selector.select();

    真正关系的阻塞点是: 读取数据

    3、NIO例子

    /**
     * NIO Socket
     */
    public class NioSocketDemo {
    	
    	private Selector selector; //通道选择器(管理器)
    	
    	
    	public static void main(String[] args) throws IOException {
    		NioSocketDemo nio = new NioSocketDemo();
    		nio.initServer(8888);
    		nio.listenSelector();
    	}
    	
    	public void initServer(int port) throws IOException{
    		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    		//设置非阻塞
    		serverSocketChannel.configureBlocking(false);
    		serverSocketChannel.socket().bind(new InetSocketAddress(port));
    		
    		this.selector = Selector.open();
    		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    		
    		
    		System.out.println("服务已启动");
    	}
    	
    	public void listenSelector() throws IOException{
    		//轮询监听selector
    		while (true) {
    			//等待客户连接
    			// select 模型,多路复用
    			this.selector.select();
    			
    			Iterator<SelectionKey> iteKey = this.selector.selectedKeys().iterator();
    			while (iteKey.hasNext()) {
    				SelectionKey key = iteKey.next();
    				iteKey.remove();
    				//处理请求
    				 handler(key);
    				
    			}
    			
    		}
    	}
    
    	/**
    	 * 处理客户端请求
    	 * @param key
    	 * @throws IOException 
    	 */
    	private void handler(SelectionKey key) throws IOException {
    		if(key.isAcceptable()){
    			//处理客户端连接请求事件
    			ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
    			SocketChannel socketChannel = serverSocketChannel.accept();
    			//设置非阻塞
    			socketChannel.configureBlocking(false);
    			//接收客户端发送的信息,需要给通道设置读的权限
    			socketChannel.register(selector, SelectionKey.OP_READ);
    		}else if (key.isReadable()){
    			//处理读的事件
    			SocketChannel socketChannel = (SocketChannel)key.channel();			
    			ByteBuffer buffer = ByteBuffer.allocate(1024);
    			int readData = socketChannel.read(buffer);
    			if(readData > 0){
    				String info = new String(buffer.array(), "GBK").trim();
    				System.out.println("服务端收到数据:" + info);
    			}else {
    				System.out.println("客户端关闭了...");
    				key.cancel();
    			}
    		}
    		
    	}
    	
    }
    

      启动Demo

      启动客户端

    打开CMD,

    按住Ctrl + ] 进入

    输入send hello world

    发出send hello world后,服务端将收到数据: hello world

    4、总结

    传统IO

  • 相关阅读:
    学习笔记2-查看目录文件
    学习笔记1-基本信息及相关目录
    【图论】二分图最大匹配
    【图论】Dinic算法
    【图论】最小割
    【数据结构】左偏树
    【数学】欧拉定理
    【数据结构】ST表
    【数学】博弈模型
    【字符串】后缀数组
  • 原文地址:https://www.cnblogs.com/linlf03/p/10463132.html
Copyright © 2020-2023  润新知