zoukankan      html  css  js  c++  java
  • QuickFix/J 源代码

    三). 客户化FIX解析
    基础知识:以下文章内容描述的前提是已经根据自己的业务规则,生成了符合要求的数据字典,并且使用QuickFix/J自带的 ant 的 jar target生成了客户化的协议解析代码。生成协议解析代码的流程和细节,请参考文章QuickFix/J 源代码研究(二)。

    1. 在QuickFix/J的设计中,为了解除message factory和相应的协议的解析代码的耦合关系,quickfix.DefaultMessageFactory会在runtime时使用 reflection动态发现解析协议的代码。因此,如果你有自定义的数据字典,并且已经根据该字典生成了解析该协议的代码,请别忘记在 DefaultMessageFactory中加入相应协议的消息工厂discoverFactory(beginString, factoryClassName)。

    2. DefaultMessageFactory有两个主要功能,一个是创建Message(根据beginString和msgType),另一个是创建 Group(根据beginString、msgType和correspondingFieldID)。相应的,根据数据字典生成的解析协议的代码中, 当然有MessageFactory了,而且这个MessageFactory当然会创建Message和Group。

    3. DefaultMessageFactory创建Message时,首先根据beginString查找相应版本的消息工厂,找到了则create相应的Message,否则new一个默认的quickfix.Message。

    4. MessageCracker的用法。当自动生成解析协议的代码之后,肯定会生成对应版本的MessageCracker。仔细阅读这个新生成的 MessageCracker,你会发现其中有很多的onMessage方法内部没有实现,并且加入了默认的throw new UnsupportedMessageType();语句。在实际使用中,用户需要创建自己的Application,并且extends quickfix.MessageCracker implements quickfix.Application。由于Override,这些throw new UnsupportedMessageType自然会被屏蔽。
    如果用户需要取到Message中的内容,做相应的业务逻辑,首先在用户的Application.fromApp中 crack(message, sessionId),crack类似message cracker的工厂,它根据message header选择相应的message cracker,然后回调相应的onMessage。onMessage正好在用户Application中Override实现。

    5. 客户化协议的客户端Initiator实现总结
    a) 创建处理类,extends MessageCracker implements quickfix.Application implements quickfix.ApplicationExtended
    b) 在fromApp中添加crack(message, sessionId);
    c) 对需要处理的消息实现相应的onMessage
    d) 创建SocketInitiator实例,填入客户化的application,messageStoreFactory,settings,logFactory,messageFactory。
    e) start initiator。

    6. 如果想把收到的每个消息单独存成一个文件备份,比如dbf之类的,该如何实现?
    a) 方案1. 实现自己的MessageStore。QuickFix/J中提供了现成的FileStore,可以将所有的消息存入同一个文件中。
    b) 方案2. 在Application的fromApp接口中,获取相应的Message,提取所需要素,存盘。
    两个方案的比较:方案2减少了一次从String到Message的解析,效率应该更高。因为MessageStore的输入是StringMessage,需要再次解析才能得到Message。

    7. FIX标准协议中规定了消息(Message)应该都至少有一个字段(Field),如果在客户化自己的FIX协议解析时,发现某些Message没有字段,则需要解除QuickFix/J中对这个条件的限制,具体在quickfix.Dictionary。

    Java代码  收藏代码
    1. private void load(Document document, String msgtype, Node node) throws ConfigError {  
    2. ...  
    3. //        if (fieldNodes.getLength() == 0) {  
    4. //            throw new ConfigError("No fields found: msgType=" + msgtype);  
    5. //        }  
    6. ...  
    7. }  



    8. 在QuickFix/J的实现中,关于不同版本的协议都有这样一个假设,就是如果Fix版本号小于等于"FIX.4.4"则是一种逻辑,大于FIX4.4 是一种逻辑。那么就需要注意在客户化时你定义的协议版本(即FIX的beginString)是多少,是不是从字符串比较的角度看小于等 于"FIX.4.4"。如果不是,则需要在诸多的地方更改QuickFix/J的逻辑。比如在quickfix.DataDictionary.load 中:

    Java代码  收藏代码
    1. private void load(InputStream inputStream) throws ConfigError {  
    2. ...  
    3.         if (beginString.startsWith(FIXT_PREFIX) || beginString.compareTo(FixVersions.FIX50) < 0) {  
    4.         ...  
    5. ...  
    6. }  



    9. QuickFix/J在实现中,默认消息(Message)头(Header)中使用的时间都是UtcTimeStamp,如果在客户化中不使用UTC时间,而使用本地时间的化,
    a) 添加本地时间的数据类型,比如LocalTimeStampField,可以仿照quickfix.UtcTimeStampField。其他还需要添加 跟本地时间相关的 LocalDateOnlyField,LocalTimeOnlyField,LocalTimeStampConverter,LocalDateOnlyConverter,LocalTimeOnlyConverter
    b) 在使用TimeStamp的地方,添加版本判断,根据版本看是使用本地时间还是UTC时间。需要修改地方大概 有:Session.doTargetTooHigh,Session.generateSequenceReset,Session.initializeResendFields,Session.validatePossDup,Session.verify。

    10. QuickFix/J在实现中,心跳设置(HeartBtInt)由客户端(Initiator)决定,而STEP协议则规定心跳由服务器端 (Acceptor),这需要修改DefaultSessionFactory.create(sessionID, settings)中关于角色和HeartBtInt的设置。并且还需要修改Session.nextLogon(message)中登陆之后读取 HeartBtInt并设置到state中的逻辑。

  • 相关阅读:
    极简风格网络消息以及分发架构
    GPS网络时间服务器是如何让集成系统协调工作的?
    北斗授时设备(NTP时间服务器)对高速联网收费的重要性
    卫星互联网路由技术现状及展望
    【Python】获取中国法定节假日的封装
    GCC 内联汇编基础
    MIT6.828——Lab1 partB(麻省理工操作系统课程实验)
    MIT6.828——Lab1 partA(麻省理工操作系统课程实验)
    bochs(2.6.11)配置安装
    MIT6.828(Step0)——实验环境配置
  • 原文地址:https://www.cnblogs.com/justuntil/p/5193958.html
Copyright © 2011-2022 走看看