昨天我们谈了怎么建立socket通信的服务端和客户端,今天我们就来谈一谈怎么封装报文。

什么是报文这里我就不在阐述了,不清楚的朋友可以自己去查资料。我们今天要谈的报文主要友以下几个部分组成:

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.建立报文的对象

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 ;
}

这样我们就能发送报文和接收报文了!赶紧试一下吧!^_^

java socket报文通信(二)报文的封装的更多相关文章

  1. Java Socket实战之二:多线程通信

    转自:http://developer.51cto.com/art/201202/317544.htm 上一篇文章说到怎样写一个最简单的Java Socket通信,但是在上一篇文章中的例子有一个问题就 ...

  2. java socket通讯(二)处理多个客户端连接

    通过java socket通讯(一) 入门示例,就可以实现服务端和客户端的socket通讯,但是上一个例子只能实现一个服务端和一个客户端之间的通讯,如果有多个客户端连接服务端,则需要通过多线程技术来实 ...

  3. java socket线程通信

    关于socket线程通信的一些知识整理 一般我们需要要让两台机子进行通信,需要创建一个Server 类,一个Client类,还需要创建一个线程类 server public class Server ...

  4. JAVA Socket编程(二)之TCP通信

    基于TCP(面向连接)的socket编程,分为客户端和服务器端. 客户端的流程如下: (1)创建套接字(socket) (2)向服务器发出连接请求(connect) (3)和服务器端进行通信(send ...

  5. Java Socket编程----通信是这样炼成的

    Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...

  6. java基础知识回顾之java Socket学习(二)--TCP协议编程

    TCP传输(传输控制协议):TCP协议是一种面向连接的,可靠的字节流服务.当客户端和服务器端彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能进行数据的传输.它将一台主机发出的字节流无差错的 ...

  7. Java Socket应用---通信是这样练成的

    网络基础简介 Java 中网络相关 API 的应用     Java 中的 InetAddress 的应用   Test01.java package com.imooc; import java.n ...

  8. JAVA知识总结(二):封装

    时隔近一年,我突然想起来这个文章还没有发完,所以就继续开始写.也不知道自己上次写到哪里了,不管了这里从面向对象的三个特性说起. 类和对象 在这之前,我们先了解什么是对象,已经什么是面向对象?对象:万物 ...

  9. Java Socket编程基础篇

    原文地址:Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Sock ...

随机推荐

  1. 【warning】clang the linker unused

    这个问题是 我在写第一个 mac os 下的helloworld遇到的 就像是 大家写第一个java中的 helloworld 肯定也是要在命令窗口下进行操作 一样 为了让一些和我一样的刚入门的孩子学 ...

  2. POJ1961 KMP算法

    POJ1961 问题重述: 输入一个长度为l的字符串S,求所有S的由字串重复排列而成的前缀,并输出前缀的长度以及该前缀的最大重复度. AC代码: //Memory: 5700K Time: 641MS ...

  3. Lua 学习笔记(二)

    七.再论lua函数 1.lua中的函数被认为是带有词法定界和第一类值    a.词法定界:被嵌套的函数可以访问外部函数的变量    b.第一类值: lua中的函数可以放在变量中    (函数指针?) ...

  4. Java学习笔记--Java8 Lambda表达式

    Java Lambda表达式入门:http://blog.csdn.net/renfufei/article/details/24600507 lambda内容的介绍:http://swiftlet. ...

  5. javascript中的一些基本方法收藏

    W3C DOM 什么是DOM,DOM其实就是把一个HTML或者XML等符合W3C标准的文档内容模拟成一个JAVA对象,这样才能给JAVA或者JS来操作.下面是JS中模拟出的内置DOM对象documen ...

  6. linux中screen命令的用法

    http://www.9usb.net/201002/linux-screen-mingling.html 作为linux服务器管理员,经常要使用ssh登陆到远程linux机器上做一些耗时的操作.也许 ...

  7. rtf表格的合并

    {\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil Calibri;}{\f1\fnil\fcharset134 \'cb\'ce\ ...

  8. Blogger安装最新文章 - Blog透视镜

    在Blogger中,是没有最新文章的网页元素,不过倒是有信息提供这个小工具,其实这就是用来新增RSS网摘用的,其中就包含最新文章的Feed,所以只要在小工具中,加入RSS网摘Feed,就可以安装最新文 ...

  9. 智能卡安全机制比较系列(五) StarCOS

    StarCOS是捷德公司的推出的智能卡COS,和前面说过的几种COS不同的是,国内的用户对于StartCOS可以说非常熟悉,而且因为握奇.明华.天喻等公司的安全机制都基本上是脱胎于StarCOS,所以 ...

  10. Feedly使用技巧

    1:用Chrome的话推荐这个应用:RSS Subscription Extension下载地址:https://chrome.google.com/webstore/detail/rss-subsc ...