QuickFIX 中的 Heartbeat 机制和 poll 系统调用
在金融领域,快速和可靠的数据交换是至关重要的。FIX(Financial Information eXchange)协议被广泛用于此目的。QuickFIX 是一个开源的 FIX 协议引擎,它提供了强大的功能来处理金融消息,其中包括会话管理和心跳(Heartbeat)机制。本文将详细介绍 QuickFIX 中的 Heartbeat 触发机制、函数调用关系,以及在 Linux 下如何使用 poll 系统调用来实现事件驱动的网络通信。
Heartbeat 触发机制和函数调用关系
在 QuickFIX 中,Heartbeat 消息的发送是通过一系列的类和函数协同工作实现的。下面是具体的触发机制和函数调用关系:
-
会话初始化和设置心跳间隔:
- 当创建一个
Session对象时,会通过配置文件或代码设置心跳间隔(heartBtInt)。 - 每个
Session对象在初始化时都会设置该心跳间隔。
- 当创建一个
-
启动 Initiator:
Initiator::start函数被调用以启动 Initiator。start函数调用onStart方法,并在一个独立的线程中运行事件循环。
-
进入事件循环:
- 在
SocketInitiator::onStart函数中,通过调用SocketConnector::block进入事件循环,阻塞等待事件的发生。 SocketConnector::block使用SocketMonitor类来监控所有的网络事件和超时事件。
- 在
-
处理超时事件:
- 当
poll系统调用检测到超时事件时,SocketMonitor::block会调用SocketConnector::onTimeout方法。 SocketConnector::onTimeout方法会遍历所有连接,并调用每个连接的onTimeout方法。
- 当
-
会话超时处理:
- 在
SocketConnection::onTimeout方法中,会调用Session::next方法来处理会话逻辑。 Session::next方法会检查是否需要发送心跳消息。
- 在
-
生成和发送心跳消息:
- 如果
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 的关系如下:
-
初始化
poll数据结构:SocketMonitor::block函数会创建一个pollfd结构体数组,其中每个结构体对应一个需要监控的文件描述符。
-
调用
poll系统调用:poll函数被调用,传入文件描述符数组及其大小,以及超时时间。poll函数阻塞,直到有事件发生或超时时间到。
-
处理
poll返回的事件:- 当
poll返回时,SocketMonitor::block函数检查每个pollfd结构体,判断哪些文件描述符上发生了事件。 - 根据发生的事件类型(如可读、可写、异常等),调用相应的回调函数。
- 当
总结
- 事件循环:
SocketInitiator::onStart函数通过调用SocketConnector::block进入事件循环,处理各种网络事件和超时事件。 - 使用
poll系统调用:在 Linux 下,SocketMonitor::block使用poll系统调用阻塞等待事件发生。 - 事件处理回调:当
poll返回时,根据发生的事件类型调用相应的回调函数处理具体的事件。
通过这些步骤和函数的协同工作,QuickFIX 能够有效地监控和处理网络事件,确保在合适的时机发送心跳消息和处理其他网络通信。这种机制确保了会话连接的稳定性和健康状态,是金融信息交换中不可或缺的部分。