You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 08:53:07