zoukankan      html  css  js  c++  java
  • 【转】编译quickfast解析库(沪深level2行情转码库)

     转自http://blog.csdn.net/hacode/article/details/7065889 

    编译quickfast解析库(沪深level2行情转码库)

    目录(?)[-]
     

    为了方便大家编译和使用QuickFast库,我在GitHub上放置了一个v1.4版本的构建环境:

    https://github.com/imharrywu/quickfast

    包括了预编译的依赖库(boost, xcerces) 以及工程管理的MPC, 同时生成了一个预编译的库在OutputRelease下。

    说明一下,对1.4的构建环境稍作了修改:

    1,使用MPC4.1,因为需要boost_system

    2,全部使用了动态库,官方编译的时候,只有boost_thread使用动态库,感觉不太协调,所以统一全部是动态库.

    3,需要boost_date_time, boost_chrono等。

    详细步骤请直接看GitHub上的README.md

    1) 下载源代码

    下载quickfast项目(windows平台):

    http://quickfast.googlecode.com/files/quickfast_win_src_1_4.zip

    公布一个QQ群:229609210 同行们可以申请加入一起讨论。

    2) 下载第三方库和配置脚本

     

    2.1) 下载activeperl

    (google it)

    2.2) 下载mpc

    http://www.ociweb.com/products/mpc

    2.3) 下载boost

    (google it)

    2.4) 下载xerces

    http://xerces.apache.org/xerces-c/

    2.5) 配置脚本

    下载 行情转码库的配置脚本setup.bat(gif文件另存为zip,解压可以得到bat文件)

    http://hi.csdn.net/attachment/201112/13/0_1323743665laAL.gif

    setup.bat配置脚本设置三方库路径和编译器选项

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. @REM 1) Customize this file by setting variables to suit your environment  
    2. @REM 2) Also you should customize QuickFAST.features to enable particular features on your system.  
    3. @REM 3) Delete the following line when you finishing customizing this file.  
    4. @REM           [==DELETED==]echo See remarks in %0 for information about setting your build environment  
    5. @REM 4) And, then run the `m.cmd' to generate *.sln & *.vcproj files  
    6. @echo off  
    7. REM =====================================================================================  
    8. REM EDIT THE FOLLOWING LINES OR SET THESE VALUES IN YOUR ENVIRONMENT BEFORE RUNNING SETUP  
    9. if "a" == "a%MPC_ROOT%" set MPC_ROOT=H:workspaceqfMPC  
    10. if "a" == "a%XERCES_ROOT%" set XERCES_ROOT=H:workspaceqfxerces-c-3.1.1-x86-windows-vc-8.0  
    11. if "a" == "a%XERCES_LIBNAME%" set XERCES_LIBNAME=xerces-c_3  
    12. if "a" == "a%BOOST_VERSION%" set BOOST_VERSION=boost_1_47_0  
    13. if "a" == "a%BOOST_ROOT%" set BOOST_ROOT=H:workspaceqf\%BOOST_VERSION%  
    14. REM END OF VALUES TO BE SET  
    15. REM =====================================================================================  

    注意:boost默认编译出来的include和lib不在同一个目录下,需要move一下。

    3) 生成项目文件

    在vc的命令行下,运行这个setup.bat && m.bat就可以生成QuickFast.sln

    若m.bat不能运行,可以尝试 perl "E:VMWareshare_70projectscpp hird_partyMPCmwc.pl" -expand_vars -use_env -type vc10 QuickFAST.mwc, 该句作用才是正式产生QuickFast.sln

    4) 编译生成QuickFast库

    vs2008打开QuickFast.sln编译连接,生成的文件在Output目录的相应配置文件夹下。

    5) 样例程序文档

    这个解决方案提供了很多例子,最简单的是TutorialApplication和InterpretApplication这2个例子。

    也可以用doxygen生成文档。

    http://hi.csdn.net/attachment/201112/26/0_1324861393eteG.gif

    6) 行情解码例子程序

    楼主用Codecs::SynchronousDecoder(同步解码器,官方例子使用的是异步解码器) 实现了一个简单的解码封装DLL,通过tcp socket从上游数据源获取fast的码流并且解码。

    同行们你们主要参考  RunDecoderLoop(...)函数内部的行情解码步骤  

    这个dll的其他代码都可以忽略, 主要关注 《第七节 行情解码的几个主要步骤》 的内容。

    这个例子是一个dll库,导出了一个API,这个API以市场代码等为参数(上海市场解码,或者深圳市场解码),开始各个市场的解码。

    同时这个API接受一组回调接口来通知数据消费者来处理解码后的行情数据, 参看 IDataExInterface 定义。

    建议大家把2个市场的解码放在2个线程里面,最好分别在2个机房里面。
     

    FAST码流是剥掉了STEP协议头以后STEP协议BODY部分用FAST编码过的内容。

    Fast_Steam Fast(STEP_PACKET -STEP_HEAD) =Fast(STEP_BODY)

    导出库的头文件

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #ifdef __cplusplus  
    2. extern "C"  
    3. {  
    4. #endif  
    5.   
    6. enum MarketTag  
    7. {  
    8.     ShenzhenMarket = 0,  
    9.     ShanghaiMarket = 1,  
    10. };  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. struct IDataExInterface /*解码以后的数据通过接口中的pNotify接口来通知客户端更新数据*/  
    2. {  
    3.     void (__stdcall * pfnFeedStatus)(ConnectionStatus connStatus);  
    4.   
    5.   
    6.     // 上海的行情数据通知接口  
    7.     void (__stdcall * pfnFeed_SHFAST30_UA3202)(const SHFAST30_UA3202_t * );  
    8.     void (__stdcall * pfnFeed_SHFAST30_UA3201)(const SHFAST30_UA3201_t * );  
    9.     void (__stdcall * pfnFeed_SHFAST30_UA3113)(const SHFAST30_UA3113_t * );  
    10.   
    11.   
    12.     // 深圳的行情数据通知接口  
    13.     void (__stdcall * pfnFeed_SZFAST_103)(const SZFAST_103_t *);  
    14.     void (__stdcall * pfnFeed_SZFAST_202)(const SZFAST_202_t *);  
    15.     void (__stdcall * pfnFeed_SZFAST_201)(const SZFAST_201_t *);  
    16.     void (__stdcall * pfnFeed_SZFAST_104)(const SZFAST_104_t *);  
    17.   
    18.   
    19. };  
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. FASTDECODER_API   
    2. int RunDecoderLoop(const char * pIp  
    3.                , unsigned short nPort  
    4.                , MarketTag nMarketTag  
    5.                , const char * templateFileName  
    6.                , const struct IDataExInterface * pNotify  
    7.                );  
    8.   
    9. #ifdef __cplusplus  
    10. };  
    11. #endif  

    客户端可以这样调用DLL

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. void Level2Thread(void * arg) // 把各个市场的解码放在各自的线程里面  
    2. {  
    3.     MarketTag nMarketTag = static_cast<MarketTag>((int)arg);  
    4.   
    5.     IDataExInterface * pNotify = new IDataExInterface;  
    6.     memset(pNotify, 0, sizeof(IDataExInterface));  
    7.     pNotify->pfnFeedStatus = FeedStatus; // 用于报告解码状态的回调  
    8.   
    9.     switch (nMarketTag)  
    10.     {  
    11.     case ShenzhenMarket:  
    12.         {  
    13.             SetThreadAffinityMask(GetCurrentThread(), 1);  
    14.             pNotify->pfnFeed_SZFAST_103         = Feed_SZFAST_103;  
    15.             pNotify->pfnFeed_SZFAST_104         = Feed_SZFAST_104;  
    16.             pNotify->pfnFeed_SZFAST_201         = Feed_SZFAST_201;  
    17.             pNotify->pfnFeed_SZFAST_202         = Feed_SZFAST_202;  
    18.             RunDecoderLoop( // 在该线程里面开始深圳市场解码  
    19.                 "127.0.0.1", 1111  
    20.                 , MarketTag(ShenzhenMarket)  
    21.                 , ".\fasttemplates_2.00.xml"  
    22.                 , pNotify);  
    23.         } break;  
    24.     case ShanghaiMarket:  
    25.         {  
    26.             SetThreadAffinityMask(GetCurrentThread(), 2);  
    27.             pNotify->pfnFeed_SHFAST30_UA3113    = Feed_SHFAST30_UA3113;  
    28.             pNotify->pfnFeed_SHFAST30_UA3201    = Feed_SHFAST30_UA3201;  
    29.             pNotify->pfnFeed_SHFAST30_UA3202    = Feed_SHFAST30_UA3202;  
    30.             RunDecoderLoop( // 在该线程里面开始上海市场解码  
    31.                 "127.0.0.1", 2222  
    32.                 , MarketTag(ShanghaiMarket)  
    33.                 , ".\template.2.03.xml"  
    34.                 , pNotify);  
    35.         } break;  
    36.     }  
    37.     return ;  
    38. }  
    39.   
    40. /** 
    41. * 简单的开启两个市场的解码线程开始解码, 
    42. * 导出函数RunDecoderLoop是一个循环解码的阻塞调用过程, 
    43. * 所以放在2个独立的线程中。 
    44. **/ int main(int argc, char* argv[])  
    45. {  
    46.     _beginthread(Level2Thread, 0, (void *)ShanghaiMarket);  
    47.     _beginthread(Level2Thread, 0, (void *)ShenzhenMarket);  
    48.     printf("Press any key to quit decoder. "); getchar();  
    49.     return 0;  
    50. }  

    7) 行情解码的几个主要步骤

    用Codecs::SynchronousDecoder解码fast的几个重要步骤

    7.1)  构造xml解析对象

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /************************************************************************ 
    2. * 全局的xml解析类 
    3. *  
    4. * 注意: 多线程同时构造parser会资源冲突 
    5. *        
    6. ************************************************************************/  
    7. static Codecs::XMLTemplateParser parser;  

    7.2) 解析xml模板生成fast模板

     
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /////////////////////////////////////////////  
    2. // Parse the templates from the template file  
    3. // errors are reported by throwing exceptions  
    4. // which are caught below.  
    5. std::ifstream tmplFile(templateFileName, openMode);  
    6. Codecs::TemplateRegistryPtr registry;  
    7. try {  
    8.    registry = parser.parse(tmplFile);  
    9. }catch (std::exception & e){  
    10.    std::cerr << e.what() << std::endl;  
    11.    return -1;  
    12. }  

    7.3) 创建一个decoder对象

     
    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //////////////////////////////////////  
    2. // Create a sync decoder and  
    3. // setup attributes.  
    4. Codecs::SynchronousDecoder * pDecoder   
    5.     = new Codecs::SynchronousDecoder(registry);  
    6. pDecoder->setHeaderBytes(0);  
    7. pDecoder->setResetOnMessage(false);  
    8. pDecoder->setLimit(0);  

    7.4) 实现一个消息消费者,并且注册给解码器

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //////////////////////////////////////  
    2. // Create an application object to use  
    3. // the incoming data.  In this case to  
    4. // accept complete messages and interpret  
    5. // them to standard out.  
    6. CMessageConsumerImpl * pHandler   
    7.     = new CMessageConsumerImpl(nMarketTag  
    8.                                , pNotify  
    9.                                , pDecoder);  
    10. //////////////////////////////////////  
    11. // and use the interpreter as the consumer  
    12. // of generic messages.  
    13. Codecs::GenericMessageBuilder builder(*pHandler);  

    7.5) 开始解码

    接收网络数据包(放置在pFastBody, 长度位nBodyLength)

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. pDataSource = new Codecs::DataSourceBuffer(pFastBody , pFastHeader->nBodyLength);  

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. try{  
    2.   pDecoder->reset();  
    3.   pDecoder->decode(*pDataSource, builder);  
    4. catch (std::exception & e)  
    5. {  
    6.   std::cout<<e.what()<<std::endl;  
    7. }  
    8. delete pDataSource;  
    9. pDataSource = NULL;  


    7.6)实现消息消费者接口

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. /// @brief A message consumer that attempts to produce a human readable version  
    2. /// of a message that has been decoded by QuickFAST.  
    3. class CMessageConsumerImpl : public Codecs::MessageConsumer  

    重写消费消息函数

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. virtual bool consumeMessage(Messages::Message & message);  

    7.7) 消费消息的过程就是消息的格式化过程


     在消息的格式化过程中,主要是遍历Message的各个filed,如果field是

    一般类型,直接转换成相应的值;如果是sequence和group,则需要将

    field转换成sequence和group,遍历;另外,由于sequence里面的每一个

    item也是一个Message结构,所以需要以Message的方式遍历结构的每一个成员;

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. foreach(item in seq)    
    2.     foreach(member in item)  

    7.8) 输出

    8) 资源下载

    =========================================================================

    项目源文件下载

    (将下面的gif链接另存为zip,解压->重命名->解压,有加密,确实有需要的朋友请留言获取)

    =========================================================================

    最新版本

    version 2.0,修改了日志打印方式和配置文件加载quickfast-v2-[8n0].zip.png

    http://hi.csdn.net/attachment/201112/27/0_132498087296Py.gif

    历史版本

    version 1.0,项目源文件Examples-8n0.zip

    http://hi.csdn.net/attachment/201112/26/0_132486187064m4.gif

  • 相关阅读:
    Java
    Linux
    Linux
    Linux
    Java
    Ansible
    Ansible
    Java
    ACM&OI 基础数论算法专题
    题解 P4781 【【模板】拉格朗日插值】
  • 原文地址:https://www.cnblogs.com/xuyuan77/p/5679351.html
Copyright © 2011-2022 走看看