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

QuickFIX/J如何处理End Of Stream错误与会话过期后重连异常

问题根因说明

Disconnecting, End Of Stream encountered报错本质是QuickFIX/J I/O层检测到服务端主动关闭了TCP连接,但没有返回合法的FIX协议报文。你遇到的循环回调问题,是因为重连时携带的过期会话标识(SenderCompID、TargetCompID、历史MsgSeqNum等)被服务端判定为无效,直接断开连接,而initiator默认的自动重连机制又不断发起重试,最终形成触发重连→被服务端断连→回调onLogout→再次触发重连的循环。

代码捕获及处理方案
  • 第一步:实现自定义SessionStateListener捕获异常状态
    QuickFIX/J w.3版本提供了SessionStateListener接口,可以直接监听会话层的异常事件,你可以在该接口的onException方法中捕获目标异常,同时完成会话清理和前端通知逻辑:
public class CustomSessionStateListener implements SessionStateListener {
    // 注入Spring WebSocket向UI推消息的工具类
    private final SimpMessagingTemplate messagingTemplate;

    public CustomSessionStateListener(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @Override
    public void onConnect(SessionID sessionID) {}

    @Override
    public void onDisconnect(SessionID sessionID) {}

    @Override
    public void onLogon(SessionID sessionID) {}

    @Override
    public void onLogout(SessionID sessionID) {}

    @Override
    public void onRefresh(SessionID sessionID) {}

    @Override
    public void onException(SessionID sessionID, Throwable cause) {
        // 匹配目标异常场景
        if (cause.getMessage().contains("End Of Stream encountered")) {
            Session expiredSession = Session.lookupSession(sessionID);
            // 停止自动重连,打断循环
            expiredSession.getLogonSchedule().setReconnectInterval(0);
            // 清理过期会话的序列号、上下文数据
            expiredSession.reset();
            // 向Angular前端推送会话过期提示
            messagingTemplate.convertAndSend("/topic/fix/session-notice", "FIX会话已过期,请重新发起登录");
        }
    }
}
  • 第二步:将自定义监听器注册到Initiator实例
    在SpringBoot初始化Initiator的配置代码中,绑定你实现的状态监听器:
@Bean
public SocketInitiator socketInitiator(Application fixApplication, MessageStoreFactory storeFactory,
                                       SessionSettings settings, LogFactory logFactory,
                                       MessageFactory messageFactory, SimpMessagingTemplate messagingTemplate) throws ConfigError {
    SocketInitiator initiator = new SocketInitiator(fixApplication, storeFactory, settings, logFactory, messageFactory);
    // 注册自定义状态监听器
    initiator.addSessionStateListener(new CustomSessionStateListener(messagingTemplate));
    return initiator;
}
  • 第三步:在toAdmin回调中增加重连校验
    toAdmin被反复调用是因为每次重连都会触发Logon报文拼装,你可以在这里增加校验逻辑,阻止无效Logon报文发送:
@Override
public void toAdmin(Message message, SessionID sessionID) throws DoNotSend {
    if (message instanceof Logon) {
        Session session = Session.lookupSession(sessionID);
        // 判断当前会话是否已经被标记为停用/过期
        if (!session.isEnabled() || (session.getReceivedLogoutReason() != null && session.getReceivedLogoutReason().contains("会话停用"))) {
            // 抛出异常直接取消本次报文发送
            throw new DoNotSend();
        }
    }
}
注意事项

不要在onLogout回调中执行会话重启、重连类逻辑,该操作会直接触发自动重连机制,加剧循环问题。如果不需要默认自动重连能力,可以直接在FIX配置文件中将ReconnectInterval参数设置为0,完全由业务层控制重连时机。

内容的提问来源于stack exchange,提问作者S Shah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:18:02