java socket发送定长报文_java socket报文通信(二)报文的封装

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

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

3位同步校验位+8位报文长度+报文头+报文体+32位MD5校验位

基本格式如下:

0X110X120X1300000232<?xml version="1.0" encoding="GBK"?>02042014122314122301000815217010001张三B251AB76B11114DB176023A0AA27A524

说明:

前面的0X110X120X13是3位16进制的同部位,这里为了大家理解,所以就以字符的形式谢出来了。00000232是报文长度。<?xml version="1.0" encoding="GBK"?>02042014122314122301000815217010001是报文头。即每个报文都包含的信息。张三是报文体。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 ;

}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux nginx 安装stream,Centos7-64bit-编译安装配置Nginx stream四层负载均衡 动态加载

Centos7-64bit-编译安装配置Nginx stream四层负载均衡 动态加载2018-08-10 17:12分享人&#xff1a;老牛yum install screen -y && screen -S nginxsudo yum -y groupinstall "Development Tools" && yum -y epel-release wget gc autoconf automake…

选择排序(java)

选择排序 选择排序是默认前面都是已经排序好的&#xff0c;然后从后面 选择最小的放在前面排序好的的后面&#xff0c;首先第一轮循环的时候默认的排序好的为空&#xff0c;然后从后面选择最小的放到数组的第一个位置&#xff0c;第二轮循环的时候默认第个元素是已经 排序好的…

asp:dropdownlist如何去掉三角箭头_科目二倒库打轮早会压库角,教练9图详解如何快速调车避免压线?...

大家都知道&#xff0c;科目二考试五项中&#xff0c;最难的项目就是倒车入库。史教练在给科二学员指导时&#xff0c;总是强调&#xff0c;练车时不要只记死点。科目二考试过程瞬息万变&#xff0c;学员在倒库过程中&#xff0c;因为脚下离合没控制好&#xff0c;速度快了&…

linux以太网连接树莓派,如何在没有Internet的情况下直接连接到树莓派

描述Raspberry Pi的多功能性意味着您一定会在室外使用它&#xff0c;而这超出了无线网络的范围。那么&#xff0c;如何在不插入键盘和显示器的情况下与之通信呢&#xff1f;不言而喻&#xff0c;在不实际的情况下&#xff0c;要拖着人为输入设备并随身携带显示器。首先需要满足…

ai钢笔工具怎么描线_AI中钢笔工具绘图的实战操作技巧!(干货满满)

下面小编将分几段分别讲述不同的钢笔工具的快捷干货操作哈&#xff0c;学会这些再加上勤学苦练保证玩的六六哒&#xff01;一、AI软件使用钢笔绘图如何断开路径绘制其他路径&#xff1f;钢笔绘制在AI中和PS的操作是一样的&#xff0c;不过有些细节大家都需要注意就是在绘制的过…

交换次数c语言,插入排序 - C中的比较和交换计数

如何计算插入排序中的比较次数和交换次数&#xff1f;我有10个随机数组。如果有人帮助我如何在这个程序中添加20,50,100,200,500,1000,2000和5000个随机数&#xff0c;我将会非常高兴。我一直在想这个很长时间&#xff0c;但仍然找不到解决办法。插入排序 - C中的比较和交换计数…

c语言查看进程模块,计算机二级考试C语言辅导:进程模块查看

环境&#xff1a;VC6.0/WinXP/SP2/1024*768分辨率个人觉得VCK应该搜寻或翻译一些框架类设计方面的文章&#xff0c;诸如MVC等一些界面、数据、操作分离的&#xff0c;或更高级的文章。写这个工具的目的&#xff1a;用来查看 DLL 是否已经成功注入到目标进程。自用辅助工具&…

二十年后我发明了保姆机器人作文_机器人保姆我的发明作文450字

机器人保姆我的发明作文450字在新疆的妈妈打电话过来说&#xff0c;一岁的小弟弟晚上总是吵吵闹闹&#xff0c;弄得妈妈每天晚上都不能睡一个安稳觉&#xff0c;已经瘦了一大圈。我决定派去年精心研制出来的机器人保姆洛克照顾远在新疆的小弟弟。机器人腾空飞起&#xff0c;在云…

幼儿园 c语言,【资源学习】c语言程序代码,登录幼儿园200个小朋友的数据

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼编写程序&#xff0c;登录幼儿园200个小朋友的数据&#xff1a;姓名、性别、年龄、身高、体重、出生日期&#xff0c;分别按年龄排序后输出。要求&#xff1a;(1)登录数据用函数input()(2)按身高排序用函数sort()(3)输出排序结果用…

android自动回复退订,Android实现短信自动回复,挂电话

原标题&#xff1a;Android实现短信自动回复&#xff0c;挂电话简单功能&#xff0c;配置一下ITelephoney,ITelephony这个接口不能直接用的。需要先在src下新建包com.android.internal.telephony&#xff0c;在其中新建一个File&#xff0c;后缀为aidl(它是一种android内部进程…

前端设置画布的高度_【后期修图】ps画布设置详解

在图像设计时少不了好的工具&#xff0c;现在当下比较流行的软件属 PS 最好&#xff0c;它的功能强大&#xff0c;是设计者的必备工具之一。在今天的内容中&#xff0c;小编要与大家分享下PS中修改画布大小的实例操作步骤&#xff0c;希望文章对大家以后的工作有所帮助。画布大…

Android插u盘自动执行,android tv box ---- 插入u盘直接播放指定文件夹中的视频

android tv box ---- 插入u盘直接播放指定文件夹中的视频思路:1.监听u盘插入广播2.遍历指定目录下的所有文件,找到视频文件3.将符合条件的文件加入播放集合中4.循环播放num one:配置AndroidManifest.xml,注册一个静态广播num two:实现广播接收者public class MyUsbReceiver ext…

down redis集群_redis有哪些集群模式

Redis集群一般有5种&#xff1a;1&#xff0c;主从复制2&#xff0c;哨兵模式3&#xff0c;Redis官方提供的Cluster集群模式(服务端)4&#xff0c;Jedis sharding集群(客户端sharding)5,利用中间件代理&#xff0c;比如豌豆荚的codis等介绍完他们的模式&#xff0c;现在来分析一…

android studio占内存大小,极大精简android studio在C盘的内存

在C盘占很大的内存大约就2种原因&#xff1a;1.SDK占内存太大2.AVD模拟器占内存太大第一种情况&#xff0c;移动SDK(用android studio不需要配置环境变量)先移动C盘的Android目录&#xff0c;里面是Sdk目录文件&#xff0c;复制到E盘&#xff0c;再删掉C盘的sdk&#xff0c;然后…

和gdi绘图效率比较_绘图计算器测评来袭!哪一款才是你AP考试的最佳拍档?

温馨提示&#xff1a;距离AP考试还有不到1个月。其中不少中国考生选择了理科科目&#xff0c;其中微积分&#xff0c;统计&#xff0c;化学&#xff0c;物理&#xff0c;生物的科目都可以使用绘图计算器。今天&#xff0c;小编收集了四款口碑不错的计算器进行测评&#xff0c;大…

android 将布局多次添加,android – 如何在布局xml中添加循环视图

您无法将aar文件添加到Eclipse中的libs文件夹(它不是jar文件)目前,使用新的RecyclerView的最佳方式是切换到Android Studio并将此依赖项添加到build.gradlecompile com.android.support:recyclerview-v7:只是一个说明.使用”占位符不是一个好习惯,但在这种情况下,您正在尝试预览…

去除小圆点_去除li小圆点以及解决其空格问题

不管是ul还是ol中的li前面始终有个小圆点&#xff0c;以前没有发现问题&#xff0c;都是直接给ul增加list-style:none;属性&#xff0c;可今天屡试不爽的属性出现问题了&#xff0c;上图通过两张截图可以清晰的看到虽然小圆点去掉了&#xff0c;但是还是占着位置。典型的占着**…

android webviewclient 点击事件,Android Api WebViewClient 详细解析

设计思想理解在WebView的设计中&#xff0c;不是什么事都要WebView类干的&#xff0c;有相当多的杂事是分给其他类做的&#xff0c;这样WebView专心干好自己的解析、渲染工作就行了。比如我们最熟知的&#xff0c;所有针对WebView的设置都封装到了WebSettings里。我们知道&…

js svg语音波动动画_11 个非常受欢迎的 JavaScript 动画库,值得学习!

1.Three.js超过46K的星星&#xff0c;这个流行的库提供了非常多的3D显示功能&#xff0c;以一种直观的方式使用 WebGL。这个库提供了、 、CSS3D 和 WebGL渲染器&#xff0c;让我们在设备和浏览器之间创建丰富的交互体验。该库于2010年4月首次推出&#xff0c;目前仍有近1000名贡…

hbuilder边框代码是什么_看懂HTML代码,摸清国外买家喜欢搜什么关键词

看懂HTML代码&#xff0c;摸清国外买家喜欢搜什么关键词大家每天都忙着找关键词&#xff0c;忙着写标题&#xff0c;忙着做各种的优化。目的就是想把自己的产品排名到前面&#xff0c;获得更多的曝光&#xff0c;带来更多的询盘。在这个过程中客服同时也是一名搜索优化人员&…