fix协议封装挑战-将一个消息实体编码为协议字符串

原创 2013年12月03日 11:31:24

消息实体如下:

package cs.test;

import java.text.SimpleDateFormat;
import java.util.Date;

import cs.mina.SeqenceNum;
import cs.mina.codec.msg.BaseMsg;
import cs.mina.codec.msg.DisclosureInstructionGrp;
import cs.mina.codec.msg.DisclosureInstructionGrpTag;
import cs.mina.codec.msg.InstrumentTag;
import cs.mina.codec.msg.NewOrderSingleMsg;
import cs.mina.codec.msg.OrderQtyDataTag;
import cs.mina.codec.msg.PartiesTag;
import cs.mina.codec.msg.Party;

/*
 *@author(huangxiaoping)
 *@date 2013-11-29
 */
public class TC_OM_04Test {
	public static BaseMsg createMsg(){
		 NewOrderSingleMsg msg=new NewOrderSingleMsg();
		 msg.getHeadEntity().getMsgSeqNum().setTagValue(SeqenceNum.getSeqence()+"");
	   	 msg.getClOrdID().setTagValue("13");
	   	 msg.getParties().setTagValue("1");
	   	 Party party=new Party();
	   	 party.getPartyID().setTagValue("1122");
	   	 party.getPartyIDSource().setTagValue("D");
	   	 party.getPartyRole().setTagValue("1");
	   	 ((PartiesTag)msg.getParties()).getChildren().add(party);
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityID().setTagValue("36");
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityIDSource().setTagValue("8");
	   	 ((InstrumentTag)msg.getInstrument()).getSecurityExchange().setTagValue("XHKG");
	   	 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS"); 
	   	 msg.getTransactTime().setTagValue(sdf.format(new Date()));
	   	 msg.getSide().setTagValue("2");
	   	 msg.getOrdType().setTagValue("2");
	   	 msg.getPrice().setTagValue("30.05");
	   	 ((OrderQtyDataTag)msg.getOrderQtyData()).getOrderQty().setTagValue("4000");
	   	 msg.getTimeInForce().setTagValue("0");
	   	 msg.getMaxPriceLevels().setTagValue("1");
	   	 msg.getExecInst().setTagValue("c x");
	   	 
	   	 DisclosureInstructionGrp dis=new DisclosureInstructionGrp();
	   	 dis.getDisclosureType().setTagValue("100");
	   	 dis.getDisclosureInstruction().setTagValue("1");
	   	((DisclosureInstructionGrpTag)msg.getDisclosureInstructionGrp()).setTagValue("1");
	   	 ((DisclosureInstructionGrpTag)msg.getDisclosureInstructionGrp()).getChildren().add(dis);
	   	 return msg;
	   	 
	   }
}



消息如下:

测试案例TC_OM_04
测试数据1
发送:
8=FIXT.1.1_9=206_35=D_49=CO99999901_56=HKEXCO_34=3_52=20131129-15:07:00.902_11=13_453=1_448=1122_447=D_452=1_18=c x_1090=1_48=36_22=8_207=XHKG_60=20131129-15:07:00.903_54=2_40=2_44=30.05_38=4000_59=0_1812=1_1813=100_1814=1_10=146_
响应:
8=FIXT.1.1_9=239_35=8_49=HKEXCO_56=CO99999901_34=3_52=20131129-07:07:01.327_1128=9_11=13_14=0_17=20701315_150=0_151=4000_1093=2_1090=1_453=1_448=1122_447=D_452=1_37=30701209_38=4000_39=0_40=2_44=30.05_207=XHKG_48=36_22=8_54=2_59=0_60=20131129-07:07:01.317_10=027_

说明:

消息的构造很简单,就是javabean,关键是如何把这个javabean解析为消息字符串。

解析原理如下:

package cs.mina.codec.msg;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import cs.mina.exception.InValidDataException;

/*
 *@author(huangxiaoping)
 *@date 2013-10-24
 */
public abstract class BaseMsg {
	public static final String SOH = "\u0001";
	protected String head;
	protected String body;
	protected String tailer;
	protected Head headEntity=new Head();
	protected Body bodyEntity=new Body();
	protected Tailer tailerEntity=new Tailer();
	
	public abstract void validate();
	
	public String encode(){
		String result="";
		List<Tag> headTagList=this.headEntity.getHeadTagList();
		for(int i=0;i<headTagList.size();i++){
			Tag headTag=headTagList.get(i);
			result+=headTag.encode();
		}
		List<Tag> bodyTagList=this.bodyEntity.getBodyTagList();
		for(int i=0;i<bodyTagList.size();i++){
			Tag bodyTag=bodyTagList.get(i);
			result+=bodyTag.encode();
		}
		List<Tag> tailerTagList=this.tailerEntity.getTailerTagList();
		for(int i=0;i<tailerTagList.size();i++){
			Tag tailerTag=tailerTagList.get(i);
			result+=tailerTag.encode();
		}
		return result;
	}
	
	public void decode(){
		decodeHead();
		decodeBody();
		decodeTailer();
	}
	
	public abstract void decodeBody();
	
	public void decodeHead(){
		Set<String> already=new HashSet<String>();
		String[] headItems=this.head.split(SOH);
		for(int i=0;i<headItems.length;i++){
			String headItem=headItems[i];
			String[] headTagItems=headItem.split("=");
			if(headTagItems.length!=2){
				throw new InValidDataException("消息格式错误");
			}
			if(already.contains(headTagItems[0])){
				throw new InValidDataException("消息格式错误");
			}
			already.add(headTagItems[0]);
			if(headTagItems[0].equals("627")){
				int skip=decodeGroup627();
				i=i+skip-1;
			}else{
				List<Tag> headTags=this.headEntity.getHeadTagList();
				for(int j=0;j<headTags.size();j++){
					Tag headTag=headTags.get(j);
					if(headTag.getTagId().equals(headTagItems[0])){
						headTag.setTagValue(headTagItems[1]);
					}
				}
			}
		}
	}
	
	private int decodeGroup627(){
		int index=head.indexOf("627=");
		String rest=head.substring(index);
		String[]tagItems=rest.split(BaseMsg.SOH);
		String[] numTagItems=tagItems[0].split("=");
		if(numTagItems.length!=2){
			throw new InValidDataException("消息格式错误");
		}
		if(!"627".equals(numTagItems[0])){
			throw new InValidDataException("消息格式错误");
		}
		int num=Integer.parseInt(numTagItems[1]);
		int count=1;
		int whileCount=0;
		((HopGrpTag)this.headEntity.getHopGrpTag()).setTagValue(num+"");
		boolean end=false;
		for(int i=0;i<num;i++){
			if(end){
				if(i!=num){
					throw new InValidDataException("消息格式错误");
				}else{
					break;
				}
			}
			HopGrp hopGrp=new HopGrp();
			((HopGrpTag)this.getHeadEntity().getHopGrpTag()).getChildren().add(hopGrp);
			while(true){
				if(whileCount>=3){
					whileCount=0;
					break;
				}
				if(tagItems.length==count){
					break;
				}
				String[] tagIt=tagItems[count].split("=");
				if(tagIt.length!=2){
					throw new InValidDataException("消息格式错误");
				}
				if(whileCount==0){
					if(!HopGrpTag.first.equals(tagIt[0])){
						throw new InValidDataException("消息格式错误");
					}
				}
				
				if(HopGrp.tagIdsSet.contains(tagIt[0])){
					List<Tag> tagList=hopGrp.getTagList();
					for(int j=0;j<tagList.size();j++){
						Tag groupTag=tagList.get(j);
						if(groupTag.getTagId().equals(tagIt[0])){
							groupTag.setTagValue(tagIt[1]);
							break;
						} 
					}
					if(tagItems.length>count+1){
						String[] nextTagIt=tagItems[count+1].split("=");
						if(nextTagIt.length!=2){
							throw new InValidDataException("消息格式错误");
						}
						if(HopGrpTag.first.equals(nextTagIt[0])){
							whileCount=0;
							count++;
							break;
						}
					}
					
					count++;
					whileCount++;
					
				}else{
					end=true;
					break;
				}
				
			}
			
		}
		
		return count;
	}
	
	public void decodeTailer(){
		Set<String> already=new HashSet<String>();
		String[] tailerItems=this.tailer.split(SOH);
		for(int i=0;i<tailerItems.length;i++){
			String tailerItem=tailerItems[i];
			String[] tailerTagItems=tailerItem.split("=");
			if(tailerTagItems.length!=2){
				throw new InValidDataException("消息格式错误");
			}
			if(already.contains(tailerTagItems[0])){
				throw new InValidDataException("消息格式错误");
			}
			already.add(tailerTagItems[0]);
			List<Tag> tailerTags=this.tailerEntity.getTailerTagList();
			for(int j=0;j<tailerTags.size();j++){
				Tag tailerTag=tailerTags.get(j);
				if(tailerTag.getTagId().equals(tailerTagItems[0])){
					tailerTag.setTagValue(tailerTagItems[1]);
				}
			}
			
		}
	}
	
	public String getHead() {
		return head;
	}

	public void setHead(String head) {
		this.head = head;
	}

	public String getBody() {
		return body;
	}

	public void setBody(String body) {
		this.body = body;
	}

	public String getTailer() {
		return tailer;
	}

	public void setTailer(String tailer) {
		this.tailer = tailer;
	}

	public Head getHeadEntity() {
		return headEntity;
	}

	public void setHeadEntity(Head headEntity) {
		this.headEntity = headEntity;
	}

	public Body getBodyEntity() {
		return bodyEntity;
	}

	public void setBodyEntity(Body bodyEntity) {
		this.bodyEntity = bodyEntity;
	}

	public Tailer getTailerEntity() {
		return tailerEntity;
	}

	public void setTailerEntity(Tailer tailerEntity) {
		this.tailerEntity = tailerEntity;
	}

	

}



消息头和消息尾是共用的,用通用的方法解析就可以了。关键是消息体,每个消息的消息体不一样,但是我们还是可以用递归的方式解析。

注意encode 方法


版权声明:本文为博主原创文章,未经博主允许不得转载。

fix协议封装挑战-数据库脚本

declare @tname varchar(8000) set @tname='' select @tname=@tname+Name+','from sysobjects where xtype=...

fix协议封装挑战-工具类

MsgUtil: /* * @headerAndBody 包含消息头+消息体,包含SOH,不包含checksum域 */ public static String ch...

fix协议封装挑战-数据有效性校验

数据校验要校验每个字段还有头和尾。 校验包过数据类型校验,特殊值校验。 数据类型校验统一写,特殊值校验写在每个消息实体里。 数据校验采用递归的方式,减少代码编写难度。 Tag类(类型校验没写完...

fix协议中消息尾校验方法

fix协议的每一条消息都分为三部分,即:消息头,消息内容,消息尾消息头和消息尾FIX 协议每个消息都包括标准消息头和标准消息尾。在标准消息头和标准消息尾中间的是消息体。消息的类型在标准消息头中标签信息...

fix协议介绍8-Reject消息

FIX.5.0SP2 Message Reject [type '3'] The reject message should be issued when a message is r...

fix协议介绍6-重发消息

FIX.5.0SP2 Message ResendRequest [type '2'] The resend request is sent by the receiving appl...

fix协议介绍3-登出消息

FIX.5.0SP2_EP168 Message Logout [type '5'] The logout message initiates or confirms the term...

Http协议(3)—HTTP实体和编码

HTTP实体实现目标         .可以被正确识别(通过Content-Type和Content-Launage)         .可以被正确解包(通过Content-Lengh...

基于TCP/IP协议的两实体通信 编码呢

package com.example.tyxiong.myapplication;import android.app.Activity; import android.os.Bundle; imp...

Objective-C 基础,类和对象,方法和消息,已声明的属性和存取方法,块对象,协议和范畴类,预定义类型和编码策略

zuij 如果你刚开始接触 iOS 或 Mac OS X 编程,首先要学习一点编程语言 Objective-C 入门知识。Objective-C 并不是一门复杂的语言,经过一段时间的接触,你就能...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:fix协议封装挑战-将一个消息实体编码为协议字符串
举报原因:
原因补充:

(最多只允许输入30个字)