本章内容其实没有多大难度,主要考察大家的细心程度.计算数据长度然后截取相应字节数组并按照协议进行解码,编码则反之。
1.基础消息的编解码
@Override
public BasicMessage decode(byte[] bytes) {int dataLength = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 2, 4));if (dataLength != bytes.length) {throw new IllegalArgumentException("The data length is incorrect.");}return new BasicMessage().setRequest(RequestType.valueOfId(ByteUtil.extract(bytes, 0, 1)[0])).setResponse(ResponseType.valueOfId(ByteUtil.extract(bytes, 1, 1)[0])).setDataLength(dataLength).setPayload(ByteUtil.extract(bytes, 6, dataLength - 1 - 1 - 4 - 8)).setTimestamp(ByteUtil.bytesToLong(ByteUtil.extract(bytes, dataLength - 8, 8)));
}@Override
public byte[] encode() {byte[] request = new byte[]{this.getRequest().getId()};byte[] response = new byte[]{this.getResponse().getId()};byte[] payload = (null == this.getPayload()) ? new byte[]{} : this.getPayload();byte[] timestamp = ByteUtil.longToBytes(this.getTimestamp(), 8);byte[] dataLength = ByteUtil.intToBytes(request.length + response.length + 4 + payload.length + timestamp.length, 4);return ByteUtil.concat(request,response,dataLength,payload,timestamp);
}
2.登入、登出消息的编解码
@Override
public Login decode(byte[] bytes) {return new Login().setLoginId(ByteUtil.bytesToShort(ByteUtil.extract(bytes, 0, 2))).setLoginInfo(new String(ByteUtil.extract(bytes, 2, bytes.length - 2), StandardCharsets.UTF_8));
}@Override
public byte[] encode() {return ByteUtil.concat(ByteUtil.shortToBytes(this.getLoginId(), 2),this.getLoginInfo().getBytes(StandardCharsets.UTF_8));
}
@Override
public Logout decode(byte[] bytes) {return new Logout().setLogoutId(ByteUtil.bytesToShort(ByteUtil.extract(bytes, 0, 2)));
}@Override
public byte[] encode() {return ByteUtil.concat(ByteUtil.shortToBytes(this.getLogoutId(), 2));
}
3.上行、下行消息的编解码
@Override
public Upstream decode(byte[] bytes) {return new Upstream().setStatus(StatusType.valueOfId(ByteUtil.extract(bytes, 0, 1)[0])).setLongitude(ByteUtil.bytesToInt(ByteUtil.extract(bytes, 1, 4))).setLatitude(ByteUtil.bytesToInt(ByteUtil.extract(bytes, 5, 4)));
}@Override
public byte[] encode() {return ByteUtil.concat(new byte[]{this.getStatus().getId()},ByteUtil.intToBytes(this.getLongitude(), 4),ByteUtil.intToBytes(this.getLatitude(), 4));
}
@Override
public Downstream decode(byte[] bytes) {return new Downstream().setCommand(CommandType.valueOfId(ByteUtil.extract(bytes, 0, 1)[0])).setStatus(StatusType.valueOfId(ByteUtil.extract(bytes, 1, 1)[0]));
}@Override
public byte[] encode() {return ByteUtil.concat(new byte[]{this.getCommand().getId()},new byte[]{this.getStatus().getId()});
}
4.文件传输、文件下载的编解码
@Override
public FileTransfer decode(byte[] bytes) {int nameLength = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 0, 1));String filename = new String(ByteUtil.extract(bytes, 1, nameLength), StandardCharsets.UTF_8);long id = ByteUtil.bytesToLong(ByteUtil.extract(bytes, 1 + nameLength, 8));int total = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 1 + nameLength + 8, 4));int index = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 1 + nameLength + 8 + 4, 4));int dataLength = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 1 + nameLength + 8 + 4 + 4, 4));byte[] content = ByteUtil.extract(bytes, 1 + nameLength + 8 + 4 + 4 + 4, dataLength);int crc = ByteUtil.crc(content, content.length);return new FileTransfer().setNameLength(nameLength).setFilename(filename).setId(id).setTotal(total).setIndex(index).setDataLength(dataLength).setContent(content).setCrc(crc);
}@Override
public byte[] encode() {byte[] filename = this.getFilename().getBytes(StandardCharsets.UTF_8);byte[] nameLength = ByteUtil.intToBytes(filename.length, 1);byte[] id = ByteUtil.longToBytes(this.getId(), 8);byte[] total = ByteUtil.intToBytes(this.getTotal(), 4);byte[] index = ByteUtil.intToBytes(this.getIndex(), 4);byte[] content = this.getContent();byte[] dataLength = ByteUtil.intToBytes(content.length, 4);byte[] crc = ByteUtil.intToBytes(ByteUtil.crc(content, content.length), 1);return ByteUtil.concat(nameLength,filename,id,total,index,dataLength,content,crc);
}
@Override
public FileDownload decode(byte[] bytes) {int nameLength = ByteUtil.bytesToInt(ByteUtil.extract(bytes, 0, 1));String filename = new String(ByteUtil.extract(bytes, 1, nameLength), StandardCharsets.UTF_8);return new FileDownload().setNameLength(nameLength).setFilename(filename);
}@Override
public byte[] encode() {byte[] filename = this.getFilename().getBytes(StandardCharsets.UTF_8);byte[] nameLength = ByteUtil.intToBytes(filename.length, 1);return ByteUtil.concat(nameLength,filename);
}