QuickFIX 中的 Heartbeat 机制

329 阅读4分钟

QuickFIX 中的 Heartbeat 机制和 poll 系统调用

在金融领域,快速和可靠的数据交换是至关重要的。FIX(Financial Information eXchange)协议被广泛用于此目的。QuickFIX 是一个开源的 FIX 协议引擎,它提供了强大的功能来处理金融消息,其中包括会话管理和心跳(Heartbeat)机制。本文将详细介绍 QuickFIX 中的 Heartbeat 触发机制、函数调用关系,以及在 Linux 下如何使用 poll 系统调用来实现事件驱动的网络通信。

Heartbeat 触发机制和函数调用关系

在 QuickFIX 中,Heartbeat 消息的发送是通过一系列的类和函数协同工作实现的。下面是具体的触发机制和函数调用关系:

  1. 会话初始化和设置心跳间隔

    • 当创建一个 Session 对象时,会通过配置文件或代码设置心跳间隔(heartBtInt)。
    • 每个 Session 对象在初始化时都会设置该心跳间隔。
  2. 启动 Initiator

    • Initiator::start 函数被调用以启动 Initiator。
    • start 函数调用 onStart 方法,并在一个独立的线程中运行事件循环。
  3. 进入事件循环

    • SocketInitiator::onStart 函数中,通过调用 SocketConnector::block 进入事件循环,阻塞等待事件的发生。
    • SocketConnector::block 使用 SocketMonitor 类来监控所有的网络事件和超时事件。
  4. 处理超时事件

    • poll 系统调用检测到超时事件时,SocketMonitor::block 会调用 SocketConnector::onTimeout 方法。
    • SocketConnector::onTimeout 方法会遍历所有连接,并调用每个连接的 onTimeout 方法。
  5. 会话超时处理

    • SocketConnection::onTimeout 方法中,会调用 Session::next 方法来处理会话逻辑。
    • Session::next 方法会检查是否需要发送心跳消息。
  6. 生成和发送心跳消息

    • 如果 Session::next 判断需要发送心跳消息(如超过了心跳间隔),则调用 Session::generateHeartbeat 方法。
    • generateHeartbeat 方法创建一个心跳消息并调用 sendRaw 方法发送该消息。

详细函数调用关系

1. SocketInitiator::start()
    -> Initiator::onStart() 
        -> while (!isStopped()) { m_connector.block(*this, false, 1.0); }

2. SocketConnector::block(Strategy& strategy, bool poll = 0, double timeout = 0.0)
    -> SocketConnector::onTimeout()
        -> SocketInitiator::onTimeout(SocketConnector&)
            -> SocketConnection::onTimeout()
                -> Session::next(UtcTimeStamp::now())
                    -> if (m_state.needHeartbeat(m_timestamper()))
                        -> Session::generateHeartbeat()
                            -> Session::sendRaw(heartbeat)

SocketConnector::block 的内部机制

SocketConnector::block 是 QuickFIX 中的一个关键函数,它用于阻塞等待各种网络事件,包括连接、读写、断开和超时事件。其内部机制依赖于 SocketMonitor 类来监控这些事件。

事件监控初始化

  • SocketMonitor 类负责监控所有网络事件。
  • SocketConnector::block 函数接受一个 Strategy 对象,该对象定义了事件发生时的回调函数。

进入事件循环

  • SocketConnector::block 函数通过调用 SocketMonitor::block 进入事件循环。
  • 在事件循环中,SocketMonitor::block 使用系统调用 poll(在 Linux 下)来监控多个文件描述符上的事件。

处理事件

  • poll 系统调用返回时,SocketMonitor::block 检查哪些文件描述符上发生了事件,并调用相应的回调函数。
  • 这些回调函数是通过 Strategy 对象传递的,用于处理具体的事件类型(如连接、读写、断开等)。

Linux 下的 poll 系统调用

在 Linux 下,poll 系统调用用于监控多个文件描述符,等待它们变为可读、可写或有异常情况发生。它的工作机制与 SocketConnector::block 的关系如下:

  1. 初始化 poll 数据结构

    • SocketMonitor::block 函数会创建一个 pollfd 结构体数组,其中每个结构体对应一个需要监控的文件描述符。
  2. 调用 poll 系统调用

    • poll 函数被调用,传入文件描述符数组及其大小,以及超时时间。
    • poll 函数阻塞,直到有事件发生或超时时间到。
  3. 处理 poll 返回的事件

    • poll 返回时,SocketMonitor::block 函数检查每个 pollfd 结构体,判断哪些文件描述符上发生了事件。
    • 根据发生的事件类型(如可读、可写、异常等),调用相应的回调函数。

总结

  • 事件循环SocketInitiator::onStart 函数通过调用 SocketConnector::block 进入事件循环,处理各种网络事件和超时事件。
  • 使用 poll 系统调用:在 Linux 下,SocketMonitor::block 使用 poll 系统调用阻塞等待事件发生。
  • 事件处理回调:当 poll 返回时,根据发生的事件类型调用相应的回调函数处理具体的事件。

通过这些步骤和函数的协同工作,QuickFIX 能够有效地监控和处理网络事件,确保在合适的时机发送心跳消息和处理其他网络通信。这种机制确保了会话连接的稳定性和健康状态,是金融信息交换中不可或缺的部分。