昨天我们讨论了如何建立套接字通信的服务器端和客户端,今天我们来谈谈如何封装消息。
这里不再赘述什么是信息,不太了解的朋友可以自己查阅资料。 今天要讲的信息主要由以下部分组成。
3位同步奇偶校验位8位消息长度消息头新闻文体32位MD5奇偶校验位
基本格式如下。
0X110X120X1300000232? xml version='1.0' encoding='GBK '? 020420141223141223010000815217010001 mgd bqb 251 ab 76 b 11114 db 176023 a 0a 27a 524
说明:
前面的0X110X120X13是3位16进制的同部位,在这里为了大家的理解,作为文字表示感谢。 00000232是消息长度。 xml version='1.0' encoding='GBK '? 02042014122314122301000815217010001是消息头。 也就是说,每个消息中包含的信息。 mgdbq是报纸的文体。 b 251 ab 76 b 11114 db 176023 a 0a 27a 524是加密数据。
在下一篇文章中将介绍如何将对象转换为xml格式,但本节主要介绍如何将上述字符串转换为字节以及如何发送和接收消息。
1 .创建消息的对象
publicclasssocketpacket { privatestringbodylen; 私有主体; 私有同步; privateString md5; publicstringgetbodylen ((returnbodylen;
}publicString getBody () ) {returnbody;
}publicString getSyncStr () {returnsyncStr;
}publicString getMd5 () {returnmd5;
} publicvoidsetbodylen (stringbodylen ) {this.bodyLen=bodyLen;
}publicvoidsetbody(stringbody ) {this.body=body;
} publicvoidsetsyncstr (stringsyncstr ) {this.syncStr=syncStr;
}publicvoidsetmd5(stringMD5 ) {this.md5=md5;
} public byte [ ] getbyte stream (throwsunsupportedencodingexception ) byte [ ] body bytes=this.body.getbytes (gbk ' body )
int bodyLength=bodyBytes.length; int socketLength=3 bodyLength 8 32; byte [ ] SOC=new byte [ socket length ]; //追加检查数据
int index=0;
soc[0]=0x11;
soc[1]=0x12;
soc[2]=0x13;
索引=3; 添加//8位消息长度(我的博文中也介绍了NumberFormat的用法) )。
numberformatnumberformat=number format.getnumber instance (;
number format.setminimumintegerdigits (8;
number format.setgroupingused (false; byte [ ] num=number format.format (socket length ).getBytes ); for(intI=0; i8; I ) {
soc[index ]=num[i];
添加主体内容
for(intI=0; I
soc[index ]=bodyBytes[i];
添加//MD5校验码
byte [ ] m D5 bytes=this.MD5.getbytes (; for(intI=0; i num.length; I ) {
soc[index ]=md5Bytes[i];
}returnsoc;
//带字节的消息字符串
公共字符串获取(byte [ ] socket bytes ) {
stringsyncstr=this.bytes tostring (socket bytes,0,3 );
stringsocketlength=this.bytes tostring (socket bytes,3,38 );
String body=this.bytesToStri
ng(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 ;
}
这样我们就能发送报文和接收报文了!赶紧试一下吧!^_^