Java使用网络字节序进行数据传输

一、消息格式

采用udp协议,协议数据有 长度、设备名称、命令编号、消息体4个字段组成

字段

长度

设备名称

命令编号

消息体

长度

4字节

2字节

1字节

变长

而消息体又包含长度、命令编号和内容

字段

长度

命令编号

内容

长度

2字节

1字节

变长

这样一个消息就包含了固定长度为7的基本消息和可变长度的消息体组成

消息体又有固定长度3和可变长度内容组成

一个基本消息可以包含多个消息体

经过分析之后开始创建Java实体类

二、创建实体类

1、创建BaseSocket(用户管理socket地址)

public class BaseSocket {

private SocketAddress socketAddress;

public SocketAddress getSocketAddress() {

return socketAddress;

}

public InetSocketAddress getInetSocketAddress(){

return (InetSocketAddress)socketAddress;

}

public void setSocketAddress(SocketAddress socketAddress) {

this.socketAddress = socketAddress;

}

public void setSocketAddress(String ip,int port){

try {

socketAddress = new InetSocketAddress( InetAddress.getByName(ip),port);

} catch (UnknownHostException e) {

}

}

public String getRemoteAddr(){

return getInetSocketAddress().getAddress().getHostAddress();

}

public int getRemotePort(){

return getInetSocketAddress().getPort();

}

}

2、创建基本消息BaseMessage

public class BaseMessage extends BaseSocket implements Serializable{

private final static Logger log = LoggerFactory.getLogger(BaseMessage .class);

private int length;//长度

private short name;//设备名称

private byte code;//命令编号

List

body;//消息体

private byte[] data;//用于存放接收的字节数组

//省略setter getter方法

}

3、创建消息体Body

public class Body {

private short length;//长度

private byte code;//命令编号

private String content;//内容 接收字符串内容

private Integer con;//内容 接收整形数据

private int conLenth;//消息体字节长度

private byte[] data;//用于接收该消息体的字节数组

//省略setter getter方法

}

三、创建工具类

1、创建大小端转换工具类PacketUtil

public class PacketUtil {

/**

* 将int转为低字节在前,高字节在后的byte数组

*/

public static byte[] toLH(int n) {

byte[] b = new byte[4];

b[0] = (byte) (n & 0xff);

b[1] = (byte) (n >> 8 & 0xff);

b[2] = (byte) (n >> 16 & 0xff);

b[3] = (byte) (n >> 24 & 0xff);

return b;

}

/**

* 将float转为低字节在前,高字节在后的byte数组

*/

public static byte[] toLH(float f) {

return toLH(Float.floatToRawIntBits(f));

}

}

2、创建对象转字节数组工具类BodyToByteUtils

public class BodyToByteUtils {

private final static int baseMessageLength = 7;//基本消息的固定长度7

private final static int bodyLength = 3;//消息体固定长度3

/**

* 对象转字节数组

* @param baseMessage

* @return

*/

public byte[] getBytes(BaseMessage baseMessage){

int len = getChildrenLength( baseMessage);

byte[] b = new byte[baseMessageLength +len];

byte[] temp;

temp = PacketUtil.toLH( baseMessageLength +len );//获取长度对应的字节数组

System.arraycopy( temp,0,b,0,4 );//拷贝长度字节数组到b 4个字节长度

temp = PacketUtil.toLH( baseMessage.getName() );//获取设备名称对应的字节数组

System.arraycopy( temp,0,b,4,2 );//拷贝设备名称字节数组到b 2个字节长度

temp = PacketUtil.toLH( baseMessage.getCode() );//获取命令编号对应的字节数组

System.arraycopy( temp,0,b,6,1 );//拷贝命令编号字节数组到b 1个字节长度

b = getChildrenBytes(temp,b,baseMessage,baseMessageLength );

return b;

}

/**

* 获取对象子消息体列表节数组

* @param temp

* @param b

* @param baseMessage

* @param start

* @return

*/

private byte[] getChildrenBytes(byte[] temp, byte[] b, BaseMessage baseMessage, int start) {

if(baseMessage.getBody()!=null && baseMessage.getBody().size()>0){

for (Body body:baseMessage.getBody()){

temp = PacketUtil.toLH( bodyLength+body.getConLenth() );//获取消息体长度对应的字节数组

System.arraycopy( temp,0,b,start,2 );//拷贝长度字节数组到b 2个字节长度

start = start +2 ;//长度+2

temp = PacketUtil.toLH( body.getCode() );//获取命令编号对应的字节数组

System.arraycopy( temp,0,b,start,1 );//拷贝命令编号字节数组到b 1个字节长度

start = start +1 ;//长度+1

if(body.getCon()!=null){

//消息体内容是整形数据时

temp = PacketUtil.toLH( body.getCon() );//获取消息体内容对应的字节数组

System.arraycopy( temp,0,b,start,body.getConLenth() );//拷贝消息体内容字节数组到b getConLenth()个字节长度

}else {

//消息体内容是字符串时

byte[] bytes = new byte[body.getConLenth()];

temp = body.getContent().getBytes();//消息体内容转字节数组

System.arraycopy(temp ,0,bytes,0,temp.length );//获取temp.length长度的消息体内容字节数组

System.arraycopy(bytes ,0,b,start,body.getConLenth() );//拷贝消息体内容字节数组到b getConLenth()个字节长度

}

start = start +body.getConLenth() ;//累加start的长度

}

}

return b;

}

/**

* 获取消息体长度

* @param baseMessage

* @return

*/

private int getChildrenLength(BaseMessage baseMessage) {

int len = 0;

if(baseMessage.getBody()!=null && baseMessage.getBody().size()>0){

for (Body body : baseMessage.getBody()){

len += body.getConLenth()+bodyLength ;

}

}

return len;

}

}

3、创建字节数组转对象工具类ByteToBodyUtils

public class ByteToBodyUtils {

private static int baseMessageLength = 7;//基本消息的固定长度7

private final static int bodyLength = 3;//消息体固定长度3

/**

* 网络字节逆序

* @param b

* @param count

* @param big

* @return

*/

public static byte[] ReversEndian(byte b[],int count, boolean big)

{

byte by;

byte data[] = new byte[count];

for(int i=0;i

{

data[i] = b[i];

}

if(big==false)

{

for(int i=0;i

{

by = b[i];

data[count-i-1] = by;

}

}

return data;

}

/**

* 字节数组转对象

* @param data

* @return

*/

public BaseMessage getBaseMessage(byte[] data){

BaseMessage baseMessage = new BaseMessage();

baseMessage.setData( data );

byte[] bytes = ReversEndian( data, 7, true );//获取 截取7个长度 并进行大小端转换后的字节数组

ByteBuffer wrap = ByteBuffer.wrap( data,6,1 );//将下标从6开始 1个长度的字节数组转成ByteBuffer 即命令编号对应的字节数组

baseMessage.setCode( wrap.get() );//获取基本消息的命令编号

baseMessage.setLength( getIntegerContent( bytes,0,4 ) );

baseMessage.setName( (short) getIntegerContent(bytes,4,2) );

List

bodyList = getBodyList( baseMessage );

baseMessage.setBody( bodyList );

return baseMessage;

}

/**

* 获取子对象列表

* @param baseMessage

* @return

*/

public List

getBodyList(BaseMessage baseMessage){

List

list = new ArrayList( );

byte[] data = baseMessage.getData();

data = ByteUtils.ReversEndian( data, data.length, true );//大小端转换

int totalLen = IpcellMessage.getLenth( data, 0, 4 );

while (baseMessageLength < totalLen){

int l = getIntegerContent( data, baseMessageLength, 2 );//返回指定位置的消息体对应的长度

byte[] aByte = getByte( data, baseMessageLength, l );//获取指定位置的消息体字节数组

byte[] bByte = getByte( aByte, 2, 1 );//返回消息体对应的消息编号字节数组

byte[] cByte = getByte( aByte, bodyLength, l-bodyLength );//返回消息体内容对应的字节数组

int code = getInt( bByte );//获取消息体对应的编号

Body body = new Body();

if(CodeUtils.contentIsStr( code )){

//如果消息编号对应的内容是字符串

String content = getContent( cByte).replace( "\u0000","" );//如果是字符串

body.setContent( content );

}else {

//如果消息编号对应的内容是整形数

int content = getBodyContent(cByte);

body.setCon( content );

}

body.setCode( (byte) code );

body.setLength( (short) l );

body.setData( cByte );

list.add( body );

baseMessageLength += l;

}

return getBodyList( baseMessage );

}

/**

* 返回消息体内容(字符串)

* @param data

* @return

*/

public static String getContent(byte[] data){

String str = "";

if(data!=null && data.length>0){

for (int i = 0;i

str += convertHexToString(ByteUtils.byteToHex( data[i] ));

}

}

return str;

}

/**

* 返回消息体内容(整形)

* @param data

* @return

*/

public static int getBodyContent(byte[] data){

ByteBuffer wrap = ByteBuffer.wrap( data,0,data.length );

return wrap.get();

}

/**

* 十六进制转ASCII

* @param hex

* @return

*/

public static String convertHexToString(String hex){

StringBuilder sb = new StringBuilder();

StringBuilder sb2 = new StringBuilder();

for( int i=0; i

String s = hex.substring(i, (i + 2));

int decimal = Integer.parseInt(s, 16);

sb.append((char)decimal);

sb2.append(decimal);

}

return sb.toString();

}

/**

* 返回十进制数

* @param data

* @param

* @param

* @return

*/

public static int getInt(byte[] data){

String hex = "";

if(data!=null && data.length>0){

for (int i = data.length-1;i>=0;i--){

hex += ByteUtils.byteToHex( data[i] );

}

}

if(StringUtils.isNotBlank( hex )){

return Integer.parseInt( hex,16 );

}

return 0;

}

/**

* 返回指定位置的字节数组

* @param data

* @param offset

* @param length

* @return

*/

public static byte[] getByte(byte[] data,int offset,int length){

byte[] bs = new byte[length];

System.arraycopy(data, offset, bs, 0, length);

return bs;

}

/**

* 返回基本信息长度

* @param data

* @param offset

* @param length

* @return

*/

public static int getIntegerContent(byte[] data,int offset,int length){

ByteBuffer wrap = ByteBuffer.wrap( data,offset,length );

return wrap.get();

}

}

java 网络序_Java使用网络字节序进行数据传输相关推荐

  1. linux网络编程一:主机字节序与网络字节序的的判断

     linux网络编程一:主机字节序与网络字节序的的判断(1)现代CPU的累加器一次能装载至少4字节(32位),即一个整数.那么这4字节在内存中排列的顺序将影响它被累加器装载成的整数值,这就是字节序问题 ...

  2. 大端字节序与小端字节序 (网络字节序与主机字节序)

    大端字节序与小端字节序 1. 简介 2. 判断机器字节序(C/C++) 3. 主机字节序与网络字节序的转换 4. IP地址与网络字节序的转换 1. 简介 字节序分为大端字节序(big endian)和 ...

  3. java 大端字节序_理解字节序 大端字节序和小端字节序

    以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/byte-order.html https://blog.csdn.net/yishengzhiai005 ...

  4. 【转】理解字节序 大端字节序和小端字节序

    转自:https://www.cnblogs.com/gremount/p/8830707.html 以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/by ...

  5. 大端字节序与小端字节序的转换

    逐步加深对字节操作的理解,记录一下大端字节序与小端字节序的转换,开发环境是vs2010,项目类型是控制台输出程序,下面是代码实现: // ByteOrder_demo.cpp : 定义控制台应用程序的 ...

  6. 大端字节序和小端字节序

    大端字节序和小端字节序 1.什么是大小端字节序 2.验证大小端字节序 1.什么是大小端字节序 计算机硬件有两种储存数据的方式:大端字节序(MSB)和 小端字节序(LSB). 小端字节序(LSB) 将这 ...

  7. 什么是字节序(端序、低端字节序、高端字节序、网络字节序)

    前言 一个内容为12(字符串)的文本文件,它的第一个字节是什么(小端序)?如果你的回答是0x32,那你真的应该好好理解下字节序了.如下图所示,我这里的正确答案是0x31.当然如果你的回答是不一定,这似 ...

  8. java网络编程_Java基础 网络编程

    主要内容 软件架构CS/BS 网络通信三要素 TCP通信 Socket套接字 ServerSocket 教学目标 能够辨别UDP和TCP协议特点 能够说出TCP协议下两个常用类名称 能够编写TCP协议 ...

  9. 字节序(小端字节序与大端字节序)

    概念: 字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序. 常见的字节序有: Little endian(小端字节序):将低序字节存储在起始地址: Big endian(大端字节序 ...

最新文章

  1. 编写程序判断等腰、等边或者普通三角形
  2. python箱线图_Python 箱线图 plt.boxplot() 参数详解
  3. 「高并发秒杀」java课程设计报告模板
  4. oracle with check option 的作用
  5. mysql 撤销权限_MySQL撤销权限(Revote语句)
  6. java是如何简化成一行代码的?-----Lambda表达式初识
  7. poj 2594 Treasure Exploration 匈牙利二分匹配+floyd
  8. vmware player 虚拟机下windows系统安装vmware tools
  9. ffmpeg 用 -ss指定起始时间
  10. .NET Reflector(.net反编译工具) v10.0.7.774 特别版(附破解步骤+注册机)
  11. Android自定义进度条拖动,Android之ProgressBar(进度条)和SeekBar(拖动条)
  12. .bat 常用命令
  13. php doctrine,数据库和Doctrine ORM
  14. 如何下载全球范围的谷歌卫星地图数据
  15. 【竞赛项目详解】二手车交易价格预测(附源码)
  16. java语言程序设计-基础篇
  17. HDU - 5984 Pocky(数学推导)
  18. 乐思蜀:我们不做网络民工
  19. soc 设计soc设计 uml实务手册_企业内训“软件需求设计建模方法学全程实例剖析”训练方案(2020年)...
  20. 百度变更使命后首个政府AI合作落地:在李彦宏老家

热门文章

  1. 主从mysql能过滤指定dml吗_MyCat教程二:mysql主从复制实现 - HG-93
  2. java swing最小化_Java swing 窗口最小化到任务栏 点击右键显示菜单(复制代码即可运行查看效果)...
  3. 自己的模块给其他人调用是怎么打包的_webpack实战——模块打包
  4. 如何区分网线是几类的_银行卡分为三类,怎么知道自己的的银行卡是几类卡?...
  5. Python函数的正确用法及其注意事项
  6. Python二十个小技巧
  7. linux vino vnc,CentOS 远程桌面(vnc,vino)
  8. C语言回调函数demo(帮助理解)以海康isapiExternDemo回调函数为例
  9. 怎么向后删除?(删除光标后的字符)(按delete键)
  10. Intel Realsense D435 python wrapper pyrealsense 类模块汇总