java 网络序_Java使用网络字节序进行数据传输
Java使用網(wǎng)絡(luò)字節(jié)序進(jìn)行數(shù)據(jù)傳輸
一、消息格式
采用udp協(xié)議,協(xié)議數(shù)據(jù)有 長度、設(shè)備名稱、命令編號、消息體4個字段組成
字段
長度
設(shè)備名稱
命令編號
消息體
長度
4字節(jié)
2字節(jié)
1字節(jié)
變長
而消息體又包含長度、命令編號和內(nèi)容
字段
長度
命令編號
內(nèi)容
長度
2字節(jié)
1字節(jié)
變長
這樣一個消息就包含了固定長度為7的基本消息和可變長度的消息體組成
消息體又有固定長度3和可變長度內(nèi)容組成
一個基本消息可以包含多個消息體
經(jīng)過分析之后開始創(chuàng)建Java實(shí)體類
二、創(chuàng)建實(shí)體類
1、創(chuàng)建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、創(chuàng)建基本消息BaseMessage
public class BaseMessage extends BaseSocket implements Serializable{
private final static Logger log = LoggerFactory.getLogger(BaseMessage .class);
private int length;//長度
private short name;//設(shè)備名稱
private byte code;//命令編號
List
body;//消息體private byte[] data;//用于存放接收的字節(jié)數(shù)組
//省略setter getter方法
}
3、創(chuàng)建消息體Body
public class Body {
private short length;//長度
private byte code;//命令編號
private String content;//內(nèi)容 接收字符串內(nèi)容
private Integer con;//內(nèi)容 接收整形數(shù)據(jù)
private int conLenth;//消息體字節(jié)長度
private byte[] data;//用于接收該消息體的字節(jié)數(shù)組
//省略setter getter方法
}
三、創(chuàng)建工具類
1、創(chuàng)建大小端轉(zhuǎn)換工具類PacketUtil
public class PacketUtil {
/**
* 將int轉(zhuǎn)為低字節(jié)在前,高字節(jié)在后的byte數(shù)組
*/
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轉(zhuǎn)為低字節(jié)在前,高字節(jié)在后的byte數(shù)組
*/
public static byte[] toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}
}
2、創(chuàng)建對象轉(zhuǎn)字節(jié)數(shù)組工具類BodyToByteUtils
public class BodyToByteUtils {
private final static int baseMessageLength = 7;//基本消息的固定長度7
private final static int bodyLength = 3;//消息體固定長度3
/**
* 對象轉(zhuǎn)字節(jié)數(shù)組
* @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 );//獲取長度對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,0,4 );//拷貝長度字節(jié)數(shù)組到b 4個字節(jié)長度
temp = PacketUtil.toLH( baseMessage.getName() );//獲取設(shè)備名稱對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,4,2 );//拷貝設(shè)備名稱字節(jié)數(shù)組到b 2個字節(jié)長度
temp = PacketUtil.toLH( baseMessage.getCode() );//獲取命令編號對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,6,1 );//拷貝命令編號字節(jié)數(shù)組到b 1個字節(jié)長度
b = getChildrenBytes(temp,b,baseMessage,baseMessageLength );
return b;
}
/**
* 獲取對象子消息體列表節(jié)數(shù)組
* @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() );//獲取消息體長度對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,start,2 );//拷貝長度字節(jié)數(shù)組到b 2個字節(jié)長度
start = start +2 ;//長度+2
temp = PacketUtil.toLH( body.getCode() );//獲取命令編號對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,start,1 );//拷貝命令編號字節(jié)數(shù)組到b 1個字節(jié)長度
start = start +1 ;//長度+1
if(body.getCon()!=null){
//消息體內(nèi)容是整形數(shù)據(jù)時
temp = PacketUtil.toLH( body.getCon() );//獲取消息體內(nèi)容對應(yīng)的字節(jié)數(shù)組
System.arraycopy( temp,0,b,start,body.getConLenth() );//拷貝消息體內(nèi)容字節(jié)數(shù)組到b getConLenth()個字節(jié)長度
}else {
//消息體內(nèi)容是字符串時
byte[] bytes = new byte[body.getConLenth()];
temp = body.getContent().getBytes();//消息體內(nèi)容轉(zhuǎn)字節(jié)數(shù)組
System.arraycopy(temp ,0,bytes,0,temp.length );//獲取temp.length長度的消息體內(nèi)容字節(jié)數(shù)組
System.arraycopy(bytes ,0,b,start,body.getConLenth() );//拷貝消息體內(nèi)容字節(jié)數(shù)組到b getConLenth()個字節(jié)長度
}
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、創(chuàng)建字節(jié)數(shù)組轉(zhuǎn)對象工具類ByteToBodyUtils
public class ByteToBodyUtils {
private static int baseMessageLength = 7;//基本消息的固定長度7
private final static int bodyLength = 3;//消息體固定長度3
/**
* 網(wǎng)絡(luò)字節(jié)逆序
* @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;
}
/**
* 字節(jié)數(shù)組轉(zhuǎn)對象
* @param data
* @return
*/
public BaseMessage getBaseMessage(byte[] data){
BaseMessage baseMessage = new BaseMessage();
baseMessage.setData( data );
byte[] bytes = ReversEndian( data, 7, true );//獲取 截取7個長度 并進(jìn)行大小端轉(zhuǎn)換后的字節(jié)數(shù)組
ByteBuffer wrap = ByteBuffer.wrap( data,6,1 );//將下標(biāo)從6開始 1個長度的字節(jié)數(shù)組轉(zhuǎn)成ByteBuffer 即命令編號對應(yīng)的字節(jié)數(shù)組
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 );//大小端轉(zhuǎn)換
int totalLen = IpcellMessage.getLenth( data, 0, 4 );
while (baseMessageLength < totalLen){
int l = getIntegerContent( data, baseMessageLength, 2 );//返回指定位置的消息體對應(yīng)的長度
byte[] aByte = getByte( data, baseMessageLength, l );//獲取指定位置的消息體字節(jié)數(shù)組
byte[] bByte = getByte( aByte, 2, 1 );//返回消息體對應(yīng)的消息編號字節(jié)數(shù)組
byte[] cByte = getByte( aByte, bodyLength, l-bodyLength );//返回消息體內(nèi)容對應(yīng)的字節(jié)數(shù)組
int code = getInt( bByte );//獲取消息體對應(yīng)的編號
Body body = new Body();
if(CodeUtils.contentIsStr( code )){
//如果消息編號對應(yīng)的內(nèi)容是字符串
String content = getContent( cByte).replace( "\u0000","" );//如果是字符串
body.setContent( content );
}else {
//如果消息編號對應(yīng)的內(nèi)容是整形數(shù)
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 );
}
/**
* 返回消息體內(nèi)容(字符串)
* @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;
}
/**
* 返回消息體內(nèi)容(整形)
* @param data
* @return
*/
public static int getBodyContent(byte[] data){
ByteBuffer wrap = ByteBuffer.wrap( data,0,data.length );
return wrap.get();
}
/**
* 十六進(jìn)制轉(zhuǎn)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();
}
/**
* 返回十進(jìn)制數(shù)
* @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;
}
/**
* 返回指定位置的字節(jié)數(shù)組
* @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();
}
}
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的java 网络序_Java使用网络字节序进行数据传输的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中延时函数_python中实
- 下一篇: shell+中sum的用法_shell高