java socket報文通訊-報文的封裝
阿新 • • 發佈:2019-01-05
什麼是報文這裡我就不在闡述了,不清楚的朋友可以自己去查資料。我們今天要談的報文主要友以下幾個部分組成:3位同步校驗位+8位報文長度+報文頭+報文體+32位MD5校驗位基本格式如下:0X110X120X1300000232<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code><Name>張三</Name></ROOT>B251AB76B11114DB176023A0AA27A524說明: 前面的0X110X120X13是3位16進位制的同部位,這裡為了大家理解,所以就以字元的形式謝出來了。00000232是報文長度。<?xml version="1.0" encoding="GBK"?><ROOT><Code>0204</Code><Date>20141223</Date><No>141223010008152</No><Code>17010001</Code></ROOT>是報文頭。即每個報文都包含的資訊。<Name>張三</Name>是報文體。B251AB76B11114DB176023A0AA27A524是加密 資料。關於如何將物件轉換為xml格式的報文我將在下一篇寫,這裡主要是給大家如何將如上的這些字串轉化為位元組以及如何傳送和接收報文。1.建立報文的物件
2.封裝傳送和接收報文的工具類
3.在封裝一個呼叫報文傳送的類:
public class SocketPacket { private String bodyLen; private String body; private String syncStr; private String md5; public String getBodyLen() { return bodyLen; } public String getBody() { return body; } public String getSyncStr() { return syncStr; } public String getMd5() { return md5; } public void setBodyLen(String bodyLen) { this.bodyLen = bodyLen; } public void setBody(String body) { this.body = body; } public void setSyncStr(String syncStr) { this.syncStr = syncStr; } public void setMd5(String md5) { this.md5 = md5; } public byte[] getByteStream() throws UnsupportedEncodingException{ 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<bodyLength;i++){ soc[index++] = bodyBytes[i]; } //新增md5校驗碼 byte [] md5Bytes = this.md5.getBytes(); for (int i = 0; i < num.length; i++) { soc[index++] = md5Bytes[i]; } return soc; } //位元組裝轉報文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,int end){ String str = ""; if(bytes.length<end-start){ return str; } byte [] bs = new byte[end-start]; for(int i = 0;i<end-start;i++){ bs[i] = bytes[start++]; } str = new String(bs); return str; } public String toString(){ return this.syncStr+this.bodyLen+this.body+this.md5; } }
2.封裝傳送和接收報文的工具類
/** * 報文傳送 */ public class SockeUtil { Socket socket = null; public SockeUtil(String ip,int port) throws UnknownHostException, IOException{ socket = new Socket(ip, port); } // public SocketPacket sentSocket(SocketPacket socketPacket) throws UnsupportedEncodingException, IOException{ SocketPacket sPacket = new SocketPacket(); 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 = new String(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"))); return sPacket; } public byte[] streamToBytes(InputStream inputStream,int len){ /** * inputStream.read(要複製到得位元組陣列,起始位置下標,要複製的長度) * 該方法讀取後input的下標會自動的後移,下次讀取的時候還是從上次讀取後移動到的下標開始讀取 * 所以每次讀取後就不需要在制定起始的下標了 */ byte [] bytes= new byte[len]; try { inputStream.read(bytes, 0, len); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return bytes; } }
3.在封裝一個呼叫報文傳送的類:
public String socket(SocketPackage socketPackage) throws UnsupportedEncodingException{
SocketClient socketClient=null;;
try {
socketClient = new SocketClient(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();
}
return result ;
}