java socket报文通信(二)报文的封装
昨天我们谈了怎么建立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报文通信(二)报文的封装的更多相关文章
- Java Socket实战之二:多线程通信
转自:http://developer.51cto.com/art/201202/317544.htm 上一篇文章说到怎样写一个最简单的Java Socket通信,但是在上一篇文章中的例子有一个问题就 ...
- java socket通讯(二)处理多个客户端连接
通过java socket通讯(一) 入门示例,就可以实现服务端和客户端的socket通讯,但是上一个例子只能实现一个服务端和一个客户端之间的通讯,如果有多个客户端连接服务端,则需要通过多线程技术来实 ...
- java socket线程通信
关于socket线程通信的一些知识整理 一般我们需要要让两台机子进行通信,需要创建一个Server 类,一个Client类,还需要创建一个线程类 server public class Server ...
- JAVA Socket编程(二)之TCP通信
基于TCP(面向连接)的socket编程,分为客户端和服务器端. 客户端的流程如下: (1)创建套接字(socket) (2)向服务器发出连接请求(connect) (3)和服务器端进行通信(send ...
- Java Socket编程----通信是这样炼成的
Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...
- java基础知识回顾之java Socket学习(二)--TCP协议编程
TCP传输(传输控制协议):TCP协议是一种面向连接的,可靠的字节流服务.当客户端和服务器端彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能进行数据的传输.它将一台主机发出的字节流无差错的 ...
- Java Socket应用---通信是这样练成的
网络基础简介 Java 中网络相关 API 的应用 Java 中的 InetAddress 的应用 Test01.java package com.imooc; import java.n ...
- JAVA知识总结(二):封装
时隔近一年,我突然想起来这个文章还没有发完,所以就继续开始写.也不知道自己上次写到哪里了,不管了这里从面向对象的三个特性说起. 类和对象 在这之前,我们先了解什么是对象,已经什么是面向对象?对象:万物 ...
- Java Socket编程基础篇
原文地址:Java Socket编程----通信是这样炼成的 Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Sock ...
随机推荐
- ORA-04021
编译或删除存储过程的时候,系统会卡住,一段时间后出现ora-04021错误. 1.可能被锁住查看v$locked select b.sid,b.serial#,b.machine,b.terminal ...
- nginx log日志分割
@echo offrem 备份并根据时间重命名错误日志文件set "cmdstr=move E:\nginx\logs\error.log E:\nginx\logs\error%date: ...
- 64位Windows 7平台安装32位Timesten,配置ODBC数据源
问题: 由于系统版本原因,客户机只能安装32位的Timesten,但客户机的平台是64位的win 7,安装完成后按照常规的控制面板->管理工具->数据源(ODBC)打开的ODBC数据源管理 ...
- 输入框提示--------百度IFE前端task2
第一版本: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...
- ajax初学
//参数说明url:请求文件地址//fnSucc:请求成功执行的函数,请求成功的条件为readyState状态码为4:且status状态码为200,status状态为浏览器请求返回的状态码//在fnS ...
- Session生命周期讨论
文章级别:Java初级 预备技能点:JSP内置对象, 监听器, 序列化 在程序开发的时候, request session appplication内置对象, 是用的比较多的 ...
- Mac下安装 php+nginx+mysql 开发环境
一.mysql安装 mysql是安装最简单顺利的 1. 首先去官方网站下载Mac适用的MySQL的dmg包 下载页面 选择图中最下方的dmg包下载进行安装 安装完成后 MySQL的安装目录为/usr/ ...
- (我国的省—市—区)三级联动数据库.sql
# MySQL-Front 5.1 (Build 2.7) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE */; /*!40101 SET SQL_MODE='' */ ...
- ecstore实现图片分离(静态资源分离)配置文件
转载http://bbs.ec-os.net/read.php?tid=854 图片分离涉及到三个config设置#define('APP_STATICS_HOST', 'http://192.168 ...
- dede分页
{dede:list pagesize ='} <div class="intro clearfix"> <ul class="pic"> ...