zoukankan      html  css  js  c++  java
  • 【转载】NIO客户端序列图

    步骤一:打开SocketChannel,绑定客户端本地地址(可选,默认系统会随机分配一个可用的本地地址),示例代码如下:

    SocketChannel clientChannel = SocketChannel.open();

    步骤二:设置SocketChannel为非阻塞模式,同时设置客户端连接的TCP参数,示例代码如下:

    clientChannel.configureBlocking(false);

    socket.setReuseAddress(true);

    socket.setReceiveBufferSize(BUFFER_SIZE);

    socket.setSendBufferSize(BUFFER_SIZE);

    步骤三:异步连接服务端,示例代码如下:

    boolean connected = clientChannel.connect(new InetSocketAddress(“ip”,port));

    步骤四:判断是否连接成功,如果连接成功,则直接注册读状态位到多路复用器中,如果当前没有连接成功(异步连接,返回false,说明客户端已经发送sync包,服务端没有返回ack包,物理链路还没有建立),示例代码如下:
    if (connected) 
    {
        clientChannel.register( selector, SelectionKey.OP_READ, ioHandler); 
    }
    else
    {
        clientChannel.register( selector, SelectionKey.OP_CONNECT, ioHandler);
    }

    步骤五:向Reactor线程的多路复用器注册OP_CONNECT状态位,监听服务端的TCP ACK应答,示例代码如下:

    clientChannel.register( selector, SelectionKey.OP_CONNECT, ioHandler);

    步骤六:创建Reactor线程,创建多路复用器并启动线程,代码如下:

    Selector selector = Selector.open();
    New Thread(new ReactorTask()).start();

    步骤七:多路复用器在线程run方法的无限循环体内轮询准备就绪的Key,代码如下:
    int num = selector.select(); 
    Set selectedKeys = selector.selectedKeys();
    Iterator it = selectedKeys.iterator();
    while (it.hasNext()) { 
    if (key.isConnectable())
         //handlerConnect(); 
    }

    步骤九:判断连接结果,如果连接成功,注册读事件到多路复用器,示例代码如下:

    if (channel.finishConnect())
        registerRead();

    步骤十:注册读事件到多路复用器:

    clientChannel.register( selector, SelectionKey.OP_READ, ioHandler);

    步骤十一:异步读客户端请求消息到缓冲区,示例代码如下:

    int  readNumber =  channel.read(receivedBuffer);

    步骤十二:对ByteBuffer进行编解码,如果有半包消息接收缓冲区Reset,继续读取后续的报文,将解码成功的消息封装成Task,投递到业务线程池中,进行业务逻辑编排,示例代码如下:

    Object message = null;
    while(buffer.hasRemain())
    {
      byteBuffer.mark();
      Object message = decode(byteBuffer);
      if (message == null)
      {
        byteBuffer.reset();
        break;
       }
      messageList.add(message );
     }
     if (!byteBuffer.hasRemain())
      byteBuffer.clear();
     else
      byteBuffer.compact();
     if (messageList != null & !messageList.isEmpty())
     {
       for(Object messageE : messageList)
       handlerTask(messageE);
     } 

    步骤十三:将POJO对象encode成ByteBuffer,调用SocketChannel的异步write接口,将消息异步发送给客户端,示例代码如下:

    socketChannel.write(buffer);

    客户端创建的时序图如下:

    原文链接如下:http://ifeve.com/netty5-user-guide/

  • 相关阅读:
    有限状态机(FSM)的简单理解和Python实现
    【Papers】Lane-Detection 近期车道线检测论文阅读总结
    刷LeetCode的简易姿势
    数码时代的效率生活
    轻量化模型训练加速的思考(Pytorch实现)
    编程之美!从线程池状态管理来看二进制操作之美
    没想到,Git居然有3种“后悔药”!
    交易系统高并发下的幂等性设计原则
    集群环境中使用Zookeeper实现分布式幂等控制
    Elasticsearch 入门到高手的成长阶梯-索引的基本操作(2)-索引的收缩和拆分
  • 原文地址:https://www.cnblogs.com/moonandstar08/p/5208190.html
Copyright © 2011-2022 走看看