• Mina Basics 04- 会话


    介绍

    会话是MINA的核心:每次客户端连接到服务器时,都会在服务器上创建一个新会话,并将保留在内存中,直到客户端断开连接。如果您在客户端使用MINA,则每次连接到服务器时,也会在客户端上创建会话。

    会话是MINA的核心:每次客户端连接到服务器时,都会在服务器上创建一个新会话,并将保留在内存中,直到客户端断开连接。如果您在客户端使用MINA,则每次连接到服务器时,也会在客户端上创建会话。

    这也是您在会话中需要执行的任何操作的访问点:发送消息,关闭会话等...

    至关重要的是要理解由于NIO的异步本质,从会话中读取并没有多大意义。实际上,当一些传入消息到达时,您的应用程序会发出信号,这是IoHandler负责处理此类事件。换句话说,不要调用session.read()。决不。

    会话状态

    会话具有状态,该状态将在时间内发展。

    1.已连接:会话已创建且可用

    2.空闲:会话至少在一段时间内没有处理任何请求(此时间段是可配置的)

        (1)空闲读:实际上没有读过一段时间

        (2)闲置写:实际上没有写过一段时间

        (3)两者都空闲:一段时间内没有读或写

    3. 关闭中:会话正在关闭(剩余的消息正在刷新,清理不会终止)

    4. 已关闭:会话现已关闭,无法通过其他方式恢复会话。这实际上不是一个真实的状态:当会话关闭时,它被删除。

    以下状态图公开了所有可能的状态和转换:

     

    我们有一组方法来获取有关会话状态的一些信息。

    会话状态:

    1.isActive():告诉会话是否有效(根据实现可能意味着不同的事情)

    2.isClosing():告诉会话是否已被关闭

    3.isConnected():告诉会话是否处于活动状态(即,不处于关闭模式)

    打开一个会话

    实际上,你无需做任何事情:它是自动的!每当远程对等方连接到服务器时,服务器将创建新连接。在客户端,每次连接到服务器时,都会创建一个会话。

    此会话作为参数传递给您的处理程序,以便您可以在应用程序中对其执行某些操作。在客户端,当您连接到服务器时,您可以通过以下方式返回创建的会话:

    ConnectFuture connectionFuture = connector.connect(address);
    connectionFuture.awaitUninterruptibly();
    if (!connectionFuture.isConnected()) { return false; } session = connectionFuture.getSession();

      

    您也可以以最短的方式完成:

    session = connector.connect(address).getSession();

    初始化

    创建新会话时,必须对其进行初始化。这是使用默认的IoService配置完成的,您可以稍后更新此配置。实际上,在创建会话时,我们会在内部创建存储在会话中的默认IoService配置的副本,这是将使用的配置实例(可以修改)。

    此初始化还将启动统计计数器,创建属性容器,将写入队列关联到会话(这是消息将被发送到其中的位置),最终,您是否提供了要执行的特定任务在这个阶段,它会调用它。

    关闭会话

    会话可以以4种方式关闭,其中两种是显式的:当远程对等方在发生异常时很好地关闭连接时,调用closeNow()方法(显式)调用closeOnFlush()方法(显式)

    (注意,不应再使用两种不推荐使用的方法:close(boolean)和close())

    显式关闭

    前两个方法可以在应用程序的任何地方调用,最大的区别是一个(closeNow())将简单地关闭会话,丢弃任何等待传输给对等方的消息,而closeOnFlush()将等待任何待处理的消息已传输给同伴。

    请注意,如果远程对等体不再连接,则使用_closeOnFlush()_调用关闭的会话将永远不会被销毁,除非您还处理其空闲状态,或者在系统TCP超时关闭套接字之前 - 可能需要几个小时 - 。始终管理应用程序中的空闲状态。

    远程对等关闭

    当远程对等方正确关闭会话时,将关闭会话,并且将丢弃所有待处理的消息。这通常是它的工作方式。

    但是,有时候,远程对等方没有正确关闭连接(这可能发生在电缆被粗暴地拔掉时)。在这种情况下,会话永远不会被告知断开连接。了解它的唯一方法是定期检查会话状态:如果它的空闲时间超过特定时间 - 必须配置 - ,然后应用程序可以决定关闭会话。否则,当达到TCP超时时,会话将最终关闭(可能需要数小时......)。

    异常

        在某些情况下,会发生导致会话关闭的例外情况。通常,在创建会话时,我们可能会遇到问题,会话将立即关闭。另一种可能性是我们不能写一些消息,例如因为频道已经关闭:我们然后关闭会话。

    总而言之,每当我们在处理会话时遇到异常时,此会话将被关闭。

    当然,您的应用程序将通过ExeptionCaught事件通知。

    配置

    可以为特定会话设置许多不同的参数:

      1.接收缓冲区大小

      2.发送缓冲区大小

      3.空闲时间

      4.写数据的超时时间

      5. ……

    加上其他配置,具体取决于使用的传输类型(参见第6章 – 传输)。

    所有这些配置参数都存储在IoSessionConfig对象中,该对象可以使用session.getConfig()方法从会话中获取。

    有关会话配置的更多信息,请参阅第4.1章 - 会话配置

    管理用户定义的属性

    可能需要存储一些可能在以后使用的数据。这是使用与每个会话相关联的专用数据结构来完成的。这是一个键值关联,可以存储开发人员可能希望在会话期间保持剩余的任何类型的数据。

    例如,如果要跟踪用户自创建会话以来发送的请求数,则可以轻松将其存储到此映射中:只需创建与此值关联的密钥即可。

    int counterValue = session.getAttribute( "counter" );
    session.setAttribute( "counter", counterValue + 1 );
    ...

    我们有办法将存储的属性处理到会话中:属性是键/值对,可以从会话的容器中添加,删除和读取。

    创建会话时会自动创建此容器,并在会话终止时将其销毁。

    会话容器

    正如我们所说,这个容器是一个键/值容器,默认为Map,但如果想要处理长寿命数据,或者如果它们很大则避免将所有这些数据存储在内存中,也可以定义另一个数据结构。 :我们可以实现一个接口和一个工厂,用于在创建会话时创建此容器。

    这段代码显示了在会话初始化期间如何创建容器:

    protected final void initSession(IoSession session,
              IoFuture future, IoSessionInitializer sessionInitializer) {
          ...
          try {
              ((AbstractIoSession) session).setAttributeMap(session.getService()
                      .getSessionDataStructureFactory().getAttributeMap(session));
          } catch (IoSessionInitializationException e) {
              throw e;
          } catch (Exception e) {
              throw new IoSessionInitializationException(
                      "Failed to initialize an attributeMap.", e);
          }

    如果我们想要定义另一种容器,这里是我们可以实现的工厂接口:

    public interface IoSessionDataStructureFactory {
      /**
      * Returns an {@link IoSessionAttributeMap} which is going to be associated
      * with the specified <tt>session</tt>.  Please note that the returned
      * implementation must be thread-safe.
      */
      IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception;
    }

    会话属性访问

    有许多方法可用于操作会话的属性:

        boolean containsAttribute(Object key):告诉是否存在给定的属性

        Object getAttribute(Object key):获取给定属性的值

        Object getAttribute(Object key,Object defaultValue):获取给定属性的值,如果不存在则获取默认值

        Set <Object> getAttributeKeys():获取所有存储属性的集合

        Object removeAttribute(Object key):删除给定的属性

        boolean removeAttribute(Object key,Object value):删除给定的属性/值对

        boolean replaceAttribute(Object key,Object oldValue,Object newValue):替换给定属性/值对

        Object setAttribute(Object key):添加没有值的新属性

        Object setAttribute(Object key,Object value):添加新的属性/值对

        Object setAttributeIfAbsent(Object key):添加一个没有值的新属性(如果它尚不存在)

        Object setAttributeIfAbsent(Object key,Object value):添加一个新的属性/值对,如果它尚不存在

    所有这些方法都允许您的应用程序存储,删除,获取或更新存储在会话中的属性。另请注意,MINA内部使用了一些属性:不要轻易修改那些你没有创建的属性!

    过滤链

    每个会话都与一系列过滤器相关联,这些过滤器将在接收或发出传入请求或传出消息时进行处理。这些过滤器是针对每个会话单独指定的,即使大多数情况下,我们将对所有现有会话使用完全相同的过滤器链。

    但是,可以动态修改单个会话的链,例如通过在链中为特定会话添加记录器筛选器。

    统计

    每个会话还会记录会话的内容:

      1.接收/发送的字节数

      2.收到/发送的消息数量

      3.空闲状态

      4.吞吐量

    和许多其他有用的信息。

    有关会话统计信息的更多信息,请参阅第4.2章 - 会话统计信息

    处理器Handler

    最后,并非最不重要的是,会话附加到Handler,负责将消息分发给您的应用程序。此处理程序还将通过使用会话发送回响应,只需调用write()方法:

      session.write( <your message> );
    

      

    第4.1章 - 会话配置

    介绍

    根据会话的类型,我们可以配置各种元素。其中一些元素在所有会话类型中共享,其他一些是特定的。

    我们目前支持4种会话风格:

      1.套接字:支持TCP传输

      2.数据报:支持UDP传输

      3.Serial:支持RS232传输

      4.VmPipe:支持IPC传输

    一般参数

    以下是所有全局参数的列表(可以为任何会话风格设置它们):

    参数

    类型

    描述

    默认值

    idleTimeForBoth

    int

    通知在读取和写入时空闲的会话之前等待的秒数

    无穷

    idleTimeForRead

    int

    通知读取空闲的会话之前等待的秒数

    无穷

    idleTimeForWrite

    int

    通知写入时空闲的会话之前等待的秒数

    无穷

    maxReadBufferSize

    int

    用于读取数据的缓冲区的最大大小

    65536 bytes

    minReadBufferSize

    int

    用于读取数据的缓冲区的最小大小

    64 bytes

    readBufferSize

    int

    用于读取incomming数据的缓冲区的默认大小

    2048 bytes

    throughputCalculationInterval

    int

    每个吞吐量计算之间的间隔(秒)。

    3s

    useReadOperation

    boolean

    当我们允许应用程序执行__session.read()_时,标志设置为TRUE

    FALSE

    writeTimeout

    int

    在挽救写入操作之前延迟等待完成

    60s

    可以通过使用getter和setter来访问所有这些参数(useReadOperation参数getter使用isUseReadOperation()方法)。

    套接字特定参数

    参数

    类型

    描述

    默认值

    defaultReuseAddress

    boolean

    SO_REUSEADDR标志的值

    true

    keepAlive

    boolean

    SO_KEEPALIVE标志的值

    false

    oobInline

    boolean

    SO_OOBINLINE标志的值

    false

    receiveBufferSize

    int

    SO_RCVBUF参数的值

    -1

    reuseAddress

    boolean

    SO_REUSEADDR标志的值

    false

    sendBufferSize

    int

    SO_SNDBUF参数的值

    -1

    soLinger

    int

    SO_LINGER参数的值

    -1

    tcpNoDelay

    boolean

    TCP_NODELAY标志的值

    false

    trafficClass

    int

    IP_TOS参数的值。 IPTOS_LOWCOST(0x02),IPTOS_RELIABILITY(0x04),IPTOS_THROUGHPUT(0x08)或IPTOS_LOWDELAY(0x10)之一

    0

    数据报特定参数

    参数

    类型

    描述

    默认值

    broadcast

    boolean

    SO_BROADCAST标志的值

    false

    closeOnPortUnreachable

    boolean

    告诉我们是否应该在端口无法访问时关闭会话

    true

    receiveBufferSize

    int

    SO_RCVBUF参数的值

    -1

    reuseAddress

    boolean

    SO_REUSEADDR标志的值

    false

    sendBufferSize

    int

    SO_SNDBUF参数的值

    -1

    trafficClass

    int

    IP_TOS参数的值。 IPTOS_LOWCOST(0x02),IPTOS_RELIABILITY(0x04),IPTOS_THROUGHPUT(0x08)或IPTOS_LOWDELAY(0x10)之一

    0

    串行特定参数

    参数

    类型

    描述

    默认值

    inputBufferSize

    int

    要使用的输入缓冲区大小

    8

    lowLatency

    boolean

    设置低延迟模式

    false

    outputBufferSize

    int

    要使用的输出缓冲区大小

    8

    receiveThreshold

    int

    以字节为单位设置接收阈值(将其设置为-1表示禁用)

    -1

    第4.2章 - 会话统计

    我们会在每个会话中保留一些有关正在发生的事情的统计数据。并非所有这些统计数据都是通过每条消息计算出来的:其中一些是按需计算的。

    参数

    类型

    描述

    默认值

    readBytes

    long

    自会话创建以来读取的总字节数

    yes

    readBytesThroughput

    double

    最后一个时间间隔内每秒读取的字节数

    no

    readMessages

    long

    自会话创建以来读取的消息总数

    yes

    readMessagesThroughput

    double

    上一个时间间隔内每秒读取的消息数

    no

    scheduledWriteBytes

    AtomicInteger

    等待写入的字节数

    yes

    scheduledWriteMessages

    AtomicInteger

    等待写入的消息数

    yes

    writtenBytes

    long

    自会话创建以来写入的总字节数

    yes

    writtenBytesThroughput

    double

    最后一个时间间隔内每秒写入的字节数

    no

    writtenMessages

    long

    自会话创建以来写入的消息总数

    yes

    writtenMessagesThroughput

    double

    在最后一个时间间隔内每秒写入的消息数

    no

    可以使用getter读取所有这些参数。

  • 相关阅读:
    【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳
    【POJ 2187】Beauty Contest 凸包+旋转卡壳
    1056: [HAOI2008]排名系统
    1874: [BeiJing2009 WinterCamp]取石子游戏
    1055: [HAOI2008]玩具取名
    2338: [HNOI2011]数矩形
    1060: [ZJOI2007]时态同步
    1054: [HAOI2008]移动玩具
    1053: [HAOI2007]反素数ant
    1052: [HAOI2007]覆盖问题
  • 原文地址:https://www.cnblogs.com/fubinhnust/p/9943289.html
Copyright © 2020-2023  润新知