socket自定义数据格式转化二进制

来源:互联网 发布:python 2.x.msi 编辑:程序博客网 时间:2024/06/06 01:16

自定义数据格式的方案

一般传送的数据,肯定有消息类型,消息序列号,具体的自定义消息内容;
则可以先定义一个统一的格式:
prefix + packType(1) + seq(4) +[userData](标志性前缀+消息类型+序列号+自定义数据)

封装成byte[] 和解析数据过程

针对上面根据每种消息类型自定义的userData,可以这样定义格式:
[filedType + filedLength+ filedValue](字段类型标志+字段长度+字段值)

直接看例子
packData ()为打包消息

public class Utils {    byte PACKET_PREFIX = '$';    int FILED_HEADER_LENGTH = 5;//因为filedType为byte + filedLength为int,所以字段前缀长度为5    int MAX_PACKET_LENGTH = 1024;//包大小 1k    int INT_LENGTH = 4;    /**     * 封装报文     * 协议:prefix + packType(1) + seq(4) +[userData]     * prefix 标志性前缀     * packType - 报文类型     * seq - 发送序列     * userData - 用户数据     *     * @param seq     * @param packType     * @param userData     * @return     */    public static byte[] packData(int seq, byte packType, byte[] userData) {        if (userData == null) {            return null;        }        byte[] data = new byte[MAX_PACKET_LENGTH];        int offset = 0;        // 打包数据头部        //add prefix        data[offset++] = PACKET_PREFIX;        //add msgType        data[offset++] = packType;        //add seq        addInt(data, offset, seq);        offset += INT_LENGTH;        if (data.length < offset + userData.length) {//数组大小不够,则需要扩容            byte[] tmp = new byte[offset + userData.length];            System.arraycopy(data, 0, tmp, 0, offset);            data = tmp;        }        System.arraycopy(userData, 0, data, offset, userData.length);        offset += userData.length;        byte[] result = new byte[offset];        System.arraycopy(data, 0, result, 0, offset);        return result;    }    public static int bytesToInt(byte[] src, int offset) {        if (src == null || src.length < offset || offset + SearchConst.INT_LENGTH > src.length) {            return -1;        }        int sendSeq;        sendSeq = src[offset++] & 0xFF;        sendSeq |= (src[offset++] << 8) & 0xFF00;        sendSeq |= (src[offset++] << 16) & 0xFF0000;        sendSeq |= (src[offset++] << 24) & 0xFF000000;        return sendSeq;    }    public static byte[] intToBytes(int value) {        byte[] src = new byte[4];        src[0] = (byte) (value & 0xFF);        src[1] = (byte) ((value >> 8) & 0xFF);        src[2] = (byte) ((value >> 16) & 0xFF);        src[3] = (byte) ((value >> 24) & 0xFF);        return src;    }    public static void addInt(byte[] src, int offset, int value) {        byte[] seqBytes = intToBytes(value);        System.arraycopy(seqBytes, 0, src, offset, 4);    }     /**     * [filedType + filedLength+ filedValue]     *     * @param src     * @param filedBytes     */    public static void addFiledBytes(byte[] src, int offset, byte[] filedBytes, byte fieldType) {        src[offset++] = fieldType;        Utils.addInt(src, offset, filedBytes.length);        offset += INT_LENGTH;        System.arraycopy(filedBytes, 0, src, offset, filedBytes.length);    }

下面为自定义的数据DeviceData 如何和byte[] 相互转化

public class DeviceData extends BaseUserData {    private static final byte FIELD_TYPE_DEVID = 0x31;    private static final byte FIELD_TYPE_SERVICENAME = 0x32;    private static final byte FIELD_TYPE_PKGNAME = 0x33;    private static final byte FIELD_TYPE_FUNCTION = 0x34;    private String devId;//设备id    private String serviceName;    private String pkgName;    private int func;//功能位    public String getDevId() {        return devId;    }    public void setDevId(String devId) {        this.devId = devId;    }    public String getServiceName() {        return serviceName;    }    public void setServiceName(String serviceName) {        this.serviceName = serviceName;    }    public String getPkgName() {        return pkgName;    }    public void setPkgName(String pkgName) {        this.pkgName = pkgName;    }    public int getFunc() {        return func;    }    public void setFunc(int func) {        this.func = func;    }    /**     * [filedType + filedLength+ filedValue]     *     * @param device     * @return     */    public static byte[] packDeviceData(DeviceData device) {        if (device == null || device.getDevId() == null || device                .getServiceName() == null || device.getPkgName() == null) {            return null;        }        try {            byte[] devIdBytes = device.getDevId().getBytes("UTF-8");            byte[] serviceNameBytes = device.getServiceName().getBytes("UTF-8");            byte[] pkgNameBytes = device.getPkgName().getBytes("UTF-8");            byte[] funcBytes = Utils.intToBytes(device.getFunc());            byte[] data = new byte[SearchConst.MAX_PACKET_LENGTH];            int offset = 0;            //add devId            Utils.addFiledBytes(data, offset, devIdBytes, FIELD_TYPE_DEVID);            offset += FILED_HEADER_LENGTH + devIdBytes.length;            //add serviceName            Utils.addFiledBytes(data, offset, serviceNameBytes, FIELD_TYPE_SERVICENAME);            offset += FILED_HEADER_LENGTH + serviceNameBytes.length;            //add pkgName            Utils.addFiledBytes(data, offset, pkgNameBytes, FIELD_TYPE_PKGNAME);            offset += FILED_HEADER_LENGTH + pkgNameBytes.length;            //add func            Utils.addFiledBytes(data, offset, funcBytes, FIELD_TYPE_FUNCTION);            byte[] result = new byte[data.length];            System.arraycopy(data, 0, result, 0, data.length);            return result;        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }        return null;    }    public static DeviceData parseDeviceUserData(byte[] userData) {        DeviceData device = new DeviceData();        if (userData.length < FILED_HEADER_LENGTH) {            return null;        }        int offset = 0;        while (offset + FILED_HEADER_LENGTH < userData.length) {            byte dataType = userData[offset++];            int len = Utils.bytesToInt(userData, offset);            offset += INT_LENGTH;            if (len < 0 || len + offset > userData.length) {                return null;            }            switch (dataType) {                case FIELD_TYPE_DEVID:                    String devId = null;                    try {                        devId = new String(userData, offset, len, "UTF-8");                    } catch (UnsupportedEncodingException e) {                        e.printStackTrace();                    }                    device.setDevId(devId);                    break;                case FIELD_TYPE_SERVICENAME:                    String serviceName = null;                    try {                        serviceName = new String(userData, offset, len, "UTF-8");                    } catch (UnsupportedEncodingException e) {                        e.printStackTrace();                    }                    device.setServiceName(serviceName);                    break;                case FIELD_TYPE_PKGNAME:                    String pkgName = null;                    try {                        pkgName = new String(userData, offset, len, "UTF-8");                    } catch (UnsupportedEncodingException e) {                        e.printStackTrace();                    }                    device.setPkgName(pkgName);                    break;                case FIELD_TYPE_FUNCTION:                    int func = Utils.bytesToInt(userData, offset);                    if (func > 0) {                        device.setFunc(func);                    }                    break;                default:            }            offset += len;        }        return device;    }    @Override    public String toString() {        return "DeviceData={ip=" + ip + ",port=" + port + ",devId=" + devId + ",serviceName=" +                serviceName + ",pkgName=" + pkgName + ",func=" + func + "}";    }}
2 0
原创粉丝点击