QuickFIX/J服务端如何处理QFJException(未知ApplVerID)异常
解决QuickFIX/J服务端处理无效DefaultApplVerID的问题
当客户端登录请求携带无效DefaultApplVerID(如55)时,错误发生在消息解析阶段(尚未进入Application接口回调流程),导致默认QFJ逻辑仅打印异常日志而未处理连接。以下是两种可行的解决思路:
方法一:自定义AcceptorIoHandler捕获异常并处理
继承默认的AcceptorIoHandler,重写exceptionCaught方法,识别Unknown or unsupported ApplVerID类型的异常后,主动断开连接或发送拒绝登录消息。
自定义IoHandler实现
import org.apache.mina.core.session.IoSession; import org.quickfixj.QFJException; import quickfix.*; import quickfix.mina.acceptor.AcceptorIoHandler; import java.util.Date; public class CustomApplVerIDAcceptorHandler extends AcceptorIoHandler { public CustomApplVerIDAcceptorHandler(Acceptor acceptor) { super(acceptor); } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { // 识别目标异常类型 if (cause instanceof QFJException && cause.getMessage().contains("Unknown or unsupported ApplVerID")) { // 先尝试发送拒绝登录消息(可选) sendRejectLogonResponse(session); // 强制断开连接 session.closeNow(); } else { // 其他异常交给父类处理 super.exceptionCaught(session, cause); } } private void sendRejectLogonResponse(IoSession session) { try { // 构造FIXT.1.1格式的拒绝登录消息 Message rejectMsg = new Message(); Header header = rejectMsg.getHeader(); // 设置基础头字段 header.setField(new BeginString("FIXT.1.1")); header.setField(new MsgType("A")); header.setField(new SenderCompID("EXCHANGE")); // 服务端CompID // 从会话中获取客户端CompID(需根据实际会话标识格式调整) String sessionKey = session.getAttribute(Session.QF_SESSION_KEY).toString(); String targetCompID = sessionKey.split("->")[1].split("/")[0]; header.setField(new TargetCompID(targetCompID)); // 设置必要字段 rejectMsg.setField(new MsgSeqNum(1)); rejectMsg.setField(new SendingTime(new Date())); rejectMsg.setField(new RefMsgSeqNum(1)); // 对应客户端登录消息的SeqNum rejectMsg.setField(new Text("无效的DefaultApplVerID,拒绝登录")); rejectMsg.setField(new SessionRejectReason(SessionRejectReason.INVALID_DATA_FIELD_VALUE)); // 计算校验和 MessageUtils.calculateChecksum(rejectMsg); // 发送消息 session.write(rejectMsg); } catch (Exception e) { // 发送失败不影响后续断开操作 e.printStackTrace(); } } }
替换默认IoHandler
初始化SocketAcceptor时,替换默认的IoHandler:
// 初始化各项依赖(application、messageStoreFactory等) SocketAcceptor acceptor = new SocketAcceptor(application, messageStoreFactory, settings, logFactory, messageFactory); // 设置自定义IoHandler acceptor.setIoHandler(new CustomApplVerIDAcceptorHandler(acceptor)); acceptor.start();
方法二:扩展数据字典支持自定义VerID(仅适用于业务允许的场景)
如果业务需要支持该自定义ApplVerID,可以修改FIXT.1.1的数据字典,添加对应的配置:
<!-- 在FIXT.1.1的字典文件中添加 --> <applVerID> <value description="自定义版本">55</value> </applVerID>
同时在服务端配置中指定该VerID对应的应用数据字典路径,但此方法仅适用于你确实需要支持该无效VerID的场景,不推荐用于纯粹的错误拦截。
内容的提问来源于stack exchange,提问作者taneryilmaz
相关产品推荐
相关产品推荐

