第4章:FIX协议会话建立——Logon消息详解、SeqNum序列号机制、心跳间隔协商
好,咱们今天聊聊FIX协议里最核心的一个环节——会话建立。
说白了,就是你的交易系统和交易所之间,怎么“握手”确认身份,然后开始干活。我见过不少新手,上来就发订单,结果被拒了,还一脸懵。其实问题就出在Logon这一步没走对。
4.1 Logon消息:会话的“敲门砖”
Logon消息,是客户端发给交易所的第一条消息。它就像你进公司大门刷的门禁卡——刷对了,门开;刷错了,抱歉,请重试。
一个标准的Logon消息长什么样?我直接给你看个例子:
8=FIX.4.4|9=123|35=A|49=CLIENT1|56=EXCHANGE|34=1|52=20240101-00:00:00|98=0|108=30|141=Y|10=234|
咱们拆开看看每个字段是干嘛的:
| 标签 | 字段名 | 说明 | 我的经验 |
|---|---|---|---|
| 35 | MsgType | 固定为'A',表示Logon | 别写错了,大写A |
| 49 | SenderCompID | 发送方ID,你的交易系统标识 | 交易所分配,别自己瞎编 |
| 56 | TargetCompID | 目标方ID,交易所的标识 | 一般交易所会提前告诉你 |
| 98 | EncryptMethod | 加密方式,0表示不加密 | 生产环境通常用1或2 |
| 108 | HeartBtInt | 心跳间隔,单位秒 | 这个值很关键,后面细说 |
| 141 | ResetSeqNumFlag | 是否重置序列号,Y/N | 首次连接建议用Y |
核心要点:Logon消息里,SenderCompID和TargetCompID必须和交易所配置的一模一样。大小写、空格都不能差。我曾经有个同事,就因为ID里多了个空格,排查了一下午。
4.2 SeqNum序列号机制:别小看这个数字
序列号,也就是34号字段MsgSeqNum。它是个计数器,从1开始,每发一条消息就加1。
为什么要有这个?你想想看,网络环境那么复杂,消息可能丢包、乱序、重复。交易所靠什么判断消息是不是重复的?就是靠序列号。
举个例子:
- 你发了序列号100的订单
- 交易所收到了,处理了
- 但你这边网络超时,没收到确认
- 你又重发了序列号100的订单
- 交易所一看,这个序列号我处理过了,直接忽略
这就是序列号防重复的核心逻辑。
我的建议:序列号一定要严格递增,不能跳号,不能重复。如果断连重连,需要和交易所协商好从哪里开始。我习惯在本地持久化存储当前序列号,每次启动时读取,确保不丢。
4.3 心跳间隔协商:108号字段的秘密
心跳,就是双方定期发一个消息,告诉对方“我还活着”。HeartBtInt(108号字段)就是心跳间隔,单位是秒。
协商过程是这样的:
- 客户端在Logon里发一个
HeartBtInt值,比如30 - 交易所收到后,会回复一个Logon确认
- 如果交易所接受你的值,它也会在回复里带上同样的
HeartBtInt - 如果交易所不接受,它会返回一个比你小的值(通常是交易所的底线)
嗯,这里要注意:心跳间隔不是越大越好,也不是越小越好。
- 设得太小(比如5秒):网络流量大,CPU开销高
- 设得太大(比如120秒):断连了要等2分钟才能发现
我个人习惯设30秒。大多数交易所也接受这个值。如果网络条件差,可以适当调大到60秒。
避坑指南:我曾经遇到过一个坑——心跳超时后,交易所会主动断开连接。但有些交易所不会发Logout消息,直接断TCP。所以你的客户端必须自己实现心跳超时检测,不能依赖交易所的通知。
4.4 知识体系总览
为了让你更直观地理解整个会话建立流程,我画了张图:
这张图把整个流程串起来了。从TCP连接开始,到Logon握手,再到心跳维持,最后才是业务消息。每一步都有它的意义,缺一不可。
4.5 实战中的几个关键点
最后,我总结几个实战中容易踩的坑:
- 序列号持久化:别把序列号放内存里,程序一重启就丢了。我习惯写到一个本地文件里,每次发消息前读一下,发完后更新。
- 心跳超时处理:如果超过
HeartBtInt * 2的时间没收到心跳,就要主动重连。别傻等。 - Logon重试:Logon失败后,不要立即重试。等几秒再试,避免被交易所当成攻击。
- ResetSeqNumFlag:首次连接或者序列号乱了,用Y。正常重连用N,保持序列号连续。
一个小技巧:调试阶段,可以把Logon消息的每个字段都打印出来,对照交易所的文档逐一检查。我当年就是这么干的,虽然慢,但稳。
好了,这一章的内容就到这。Logon消息、序列号、心跳间隔,这三个东西搞明白了,FIX协议的会话建立你就掌握了八成。剩下的,就是在实战中慢慢积累了。
公众号:蓝海资料掘金营,微信deep3321