报文 组包 解包
在实际项目中经常会碰到不同系统之间的数据交换,有些是用webservice。有些则是使用发socket消息的方式,将需要发送的消息组装成特定格式的字符串或Xml格式的文件,再通过socket编程发送到对方系统。本文主要讨论组装成定长字符串。
抽象任何一个定长消息包(MsgPackage)都是由一个或多个消息片(MsgPiece)组成。任何一个消息片都是由一个或多个消息域(MsgField)组成。消息域的属性有:域名、长度、值、如果值的长度小于定义的最大长度那值是靠左还是右对齐其余的是用什么字符填充。
工具代码
消息域类
package socket.msg;
/**
* 消息域
* @author Zhenwei.Zhang (2013-9-25)
*/
public class MsgField {
public MsgField (String name, int length, char fillChar, FillSide fillSide) {
this.name = name;
this.length = length;
this.fillChar = fillChar;
this.fillSide = fillSide;
}
/**
* 填充位置
* @author Zhenwei.Zhang (2013-9-25)
*/
public enum FillSide {
LEFT, RIGHT
}
/** 域名称 */
private String name;
/** 长度 */
private int length;
/** 填充字符 */
private char fillChar;
/** 填充位置 */
private FillSide fillSide;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public char getFillChar() {
return fillChar;
}
public void setFillChar(char fillChar) {
this.fillChar = fillChar;
}
public FillSide getFillSide() {
return fillSide;
}
public void setFillSide(FillSide fillSide) {
this.fillSide = fillSide;
}
}
报文消息片类
package socket.msg;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import socket.msg.MsgField.FillSide;
/**
* 消息片,由多个消息域按一定的顺序组成
* @author Zhenwei.Zhang (2013-9-25)
*/
public abstract class MsgPiece {
/** 消息域列表 */
private List itemList = new LinkedList();
public MsgPiece(MsgField[] items) {
itemList = new LinkedList();
for (int i = 0; i < items.length; i++) {
itemList.add(items[i]);
}
}
/**
* 组消息
* @author Zhenwei.Zhang (2013-9-25)
* @param charsetName
* @return
* @throws Exception
*/
public byte[] pack(String charsetName) throws Exception {
StringBuffer result = new StringBuffer();
byte[] b = null;
try {
for (MsgField item : itemList) {
PropertyDescriptor pd = new PropertyDescriptor(item.getName(), this.getClass());
Method readMethod = pd.getReadMethod();
Object gotVal = readMethod.invoke(this);
String strFill = gotVal == null ? "" : gotVal.toString();
res