java 网络序_Java使用网络字节序进行数据传输
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();
}
}
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的java 网络序_Java使用网络字节序进行数据传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中延时函数_python中实
- 下一篇: java记事本应用程序_Java教程:使