Python FIX发起方应用Socket接收时存在部分消息的问题求助
Python FIX发起方应用Socket接收时存在部分消息的问题求助
嘿,我瞅了你这段接收FIX消息的代码,问题根源太明显了——你用了完全错误的逻辑来判断消息接收完成!
TCP是流式传输,根本不会按照你想象的“固定包大小”来发送数据,你写的if len(chunk)<chunk_size: break这行代码简直是给自己挖坑:只要某次接收的字节数小于设定的2048,就直接停止接收,这直接导致后续的消息内容被截断,出现你说的“一个完整+一个部分”“剩下的部分”这种情况。
而且FIX消息本身有明确的协议规范,完全不需要靠包大小判断边界!每个FIX消息都以SOH字符(\x01)结尾,还能通过9字段(BodyLength)和10字段(校验和)来确定完整消息的长度,咱们得按协议规则来处理才对。
给你改一下代码,按照FIX协议的正确姿势来接收消息:
首先,写一个工具函数,从字节流里拆分出完整的FIX消息:
def extract_fix_messages(buffer): messages = [] soh = b'\x01' # FIX消息的结尾是10=xxx\x01,咱们靠这个定位完整消息 while True: # 先找校验和字段的起始位置 checksum_start = buffer.find(b'10=') if checksum_start == -1: break # 还没找到完整的结尾字段,退出循环 # 10=xxx\x01的结构是:b'10=' + 3位数字 + b'\x01',所以SOH在checksum_start+6的位置(0索引) soh_pos = checksum_start + 6 if soh_pos >= len(buffer) or buffer[soh_pos:soh_pos+1] != soh: break # 没找到对应的SOH,说明还不是完整消息 # 截取完整消息,更新buffer为剩余字节 full_msg = buffer[:soh_pos+1] messages.append(full_msg) buffer = buffer[soh_pos+1:] return messages, buffer
然后修改你的接收函数,持续接收直到拿到完整消息,同时保留未处理的剩余字节:
socket_local = socket.create_connection((address, port)) socket_local.settimeout(1.0) # 0.001的超时太苛刻了,很容易错过数据,调大一点 chunk_size = 2048 # 把buffer设成全局的,这样下次接收能延续上次的剩余数据 remaining_buffer = b'' def listen_message(): global remaining_buffer buffer = remaining_buffer while True: try: chunk = socket_local.recv(chunk_size) if not chunk: print("连接已关闭") break buffer += chunk # 尝试提取完整的FIX消息 full_messages, remaining = extract_fix_messages(buffer) if full_messages: # 保存剩余字节,下次用 remaining_buffer = remaining # 如果一次收到多个消息,这里可以返回列表,我先返回第一个完整的 return full_messages[0] except socket.timeout: print("接收超时,当前缓存有未处理的部分数据") # 把剩余数据存起来,下次继续接收 remaining_buffer = buffer break # 如果循环结束还没拿到完整消息,返回当前缓存的部分数据(或者根据业务处理) remaining_buffer = buffer return buffer
为啥这么改?给你掰扯清楚:
- 完全按照FIX协议的规则识别完整消息,再也不用不靠谱的包大小判断了
- 用全局的
remaining_buffer保存每次接收后剩下的部分消息,下次接收时继续拼接,不会丢失数据 - 调整了超时时间,0.001毫秒的超时几乎等于不让系统有时间接收数据,很容易导致只拿到部分字节
另外提醒你:如果你的场景里会一次收到多个完整的FIX消息,extract_fix_messages会返回所有完整消息的列表,你可以根据业务需求批量处理,不用只返回第一个。
备注:内容来源于stack exchange,提问作者nily
相关产品推荐
相关产品推荐

