昨天我们谈了怎么建立socket通信的服务端和客户端,今天我们就来谈一谈怎么封装报文。
什么是报文这里我就不在阐述了,不清楚的朋友可以自己去查资料。我们今天要谈的报文主要友以下几个部分组成:
3位同步校验位+8位报文长度+报文头+报文体+32位MD5校验位
基本格式如下:
0X110X120X1300000232<?xml version="1.0" encoding="GBK"?>0204
2014122314122301000815217010001
张三B251AB76B11114DB176023A0AA27A524
说明:
前面的0X110X120X13是3位16进制的同部位,这里为了大家理解,所以就以字符的形式谢出来了。00000232是报文长度。<?xml version="1.0" encoding="GBK"?>0204
2014122314122301000815217010001
是报文头。即每个报文都包含的信息。张三是报文体。B251AB76B11114DB176023A0AA27A524是加密数据。
关于如何将对象转换为xml格式的报文我将在下一篇写,这里主要是给大家如何将如上的这些字符串转化为字节以及如何发送和接收报文。
1.建立报文的对象
public classSocketPacket {privateString bodyLen;privateString body;privateString syncStr;privateString md5;publicString getBodyLen() {returnbodyLen;
}publicString getBody() {returnbody;
}publicString getSyncStr() {returnsyncStr;
}publicString getMd5() {returnmd5;
}public voidsetBodyLen(String bodyLen) {this.bodyLen =bodyLen;
}public voidsetBody(String body) {this.body =body;
}public voidsetSyncStr(String syncStr) {this.syncStr =syncStr;
}public voidsetMd5(String md5) {this.md5 =md5;
}public byte[] getByteStream() throwsUnsupportedEncodingException{byte[] bodyBytes = this.body.getBytes("gbk");//获得body的字节数组
int bodyLength =bodyBytes.length;int socketLength = 3+bodyLength+8+32;byte [] soc = new byte[socketLength];//添加校验数据
int index = 0;
soc[0]=0x11;
soc[1]=0x12;
soc[2]=0x13;
index+=3;//添加8位报文长度(我的博文中也有NumberFormat的用法介绍)
NumberFormat numberFormat =NumberFormat.getNumberInstance();
numberFormat.setMinimumIntegerDigits(8);
numberFormat.setGroupingUsed(false);byte [] num =numberFormat.format(socketLength).getBytes();for(int i = 0;i<8;i++){
soc[index++]=num[i];
}//添加body内容
for(int i = 0;i
soc[index++] =bodyBytes[i];
}//添加md5校验码
byte [] md5Bytes = this.md5.getBytes();for (int i = 0; i < num.length; i++) {
soc[index++] =md5Bytes[i];
}returnsoc;
}//字节装转报文string
public String getString(byte[] socketBytes){
String syncStr= this.bytesToString(socketBytes, 0, 3);
String socketLength= this.bytesToString(socketBytes, 3, 3+8);
String body= this.bytesToString(socketBytes, 3+8, socketBytes.length-32);
String md5= this.bytesToString(socketBytes,socketBytes.length-32,socketBytes.length);return syncStr+socketLength+body+md5;
}//将字节数组转化为string
public String bytesToString(byte [] bytes,int start,intend){
String str= "";if(bytes.length
}byte [] bs = new byte[end-start];for(int i = 0;i
bs[i]= bytes[start++];
}
str= newString(bs);returnstr;
}publicString toString(){return this.syncStr+this.bodyLen+this.body+this.md5;
}
}
2.封装发送和接收报文的工具类
/*** 报文发送*/
public classSockeUtil {
Socket socket= null;public SockeUtil(String ip,int port) throwsUnknownHostException, IOException{
socket= newSocket(ip, port);
}// public SocketPacket sentSocket(SocketPacket socketPacket) throwsUnsupportedEncodingException, IOException{
SocketPacket sPacket= newSocketPacket();
OutputStream output=null;
InputStream input=null;//同步字符串(3byte)
byte[] sync = null; // byte[] bodyLen = null; //8位长度
byte[] body = null; //内容
byte[] md5 = null; //MD5
output =socket.getOutputStream();//写数据发送报文
output.write(socketPacket.getByteStream());//获得服务端返回的数据
input =socket.getInputStream();
sync= this.streamToBytes(input,3);
bodyLen= this.streamToBytes(input, 8);
String lenString= newString(bodyLen);int len =Integer.valueOf(lenString);
body= this.streamToBytes(input, len);
md5= this.streamToBytes(input, 32);
sPacket.setSyncStr(new String(sync,Charset.forName("gbk")));
socketPacket.setBodyLen(new String(bodyLen,Charset.forName("gbk")));
socketPacket.setBody(new String(body,Charset.forName("gbk")));
socketPacket.setMd5(new String(md5,Charset.forName("gbk")));returnsPacket;
}public byte[] streamToBytes(InputStream inputStream,intlen){/*** inputStream.read(要复制到得字节数组,起始位置下标,要复制的长度)
* 该方法读取后input的下标会自动的后移,下次读取的时候还是从上次读取后移动到的下标开始读取
* 所以每次读取后就不需要在制定起始的下标了*/
byte [] bytes= new byte[len];try{
inputStream.read(bytes,0, len);
}catch(IOException e) {//TODO Auto-generated catch block
e.printStackTrace();
}returnbytes;
}
}
3.在封装一个调用报文发送的类:
public String socket(SocketPackage socketPackage) throwsUnsupportedEncodingException{
SocketClient socketClient=null;;try{
socketClient= newSocketClient(ip,端口);
}catch(UnknownHostException e) {
log.error("socket链接异常,链接信息:"+ip+端口);
e.printStackTrace();
}catch(IOException e) {
log.error("socket IO异常");
e.printStackTrace();
}
SocketPackage s= null;try{
s=socketClient.sendMsg(socketPackage);
}catch(Exception e) {try{
log.error("socket发送消息异常,发送信息:"+new String(socketPackage.getByteStream(),"GBK"));
}catch(UnsupportedEncodingException e1) {
log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());
e1.printStackTrace();
}
e.printStackTrace();
}
String result= "";try{
result= new String(s.getStream(),"GBK");
}catch(UnsupportedEncodingException e) {
log.error("socket将socketPackage转为字符串异常,socketPackage信息:"+socketPackage.getByteStream());
e.printStackTrace();
}returnresult ;
}
这样我们就能发送报文和接收报文了!赶紧试一下吧!^_^