2016-10-31 2 views
1

UDPクライアントサーバーを作成しようとしています。JavaオブジェクトからUDPバイト[]

UINT8 type;   
UINT8 flags;    
UINT16 len;     
UINT32 sequenceN;   
UINT16 startIdx;   
UINT16 endIdx; 

対応するJavaオブジェクトは、次のとおりです:

[受信メッセージはBIG_ENDIANで、構造はこれです:私はすでに、次の操作を実行して、メッセージを読み取ることができています変換するには

short type; 
short flags; 
int len; 
long sequenceN; 
int startIdx; 
int endIdx; 

UDPからJavaへ私は以下を使用します:

typeArray = Arrays.copyOfRange(msg, 0, 1); 
type = Util.reassembleShort(typeArray); 
flagsArray = Arrays.copyOfRange(msg, 1, 2); 
flags = Util.reassembleShort(flagsArray); 
lenArray = Arrays.copyOfRange(msg, 2, 4); 
len = Util.reassembleInt(lenArray); 
seqArray = Arrays.copyOfRange(msg, 4, 8); 
sequenceN = Util.reassembleLong(seqArray); 
startArray = Arrays.copyOfRange(msg, 8, 10); 
startIdx = Util.reassembleInt(startArray); 
endArray = Arrays.copyOfRange(msg, 10, 12); 
endIdx = Util.reassembleInt(endArray); 

バイトを再アセンブルするには私は(上記Util.reassembleへAKAの呼び出し*)以下を使用するJavaオブジェクトへの配列部分:

ショート

ByteBuffer buffer = ByteBuffer.wrap(input); 
buffer.order(ByteOrder.BIG_ENDIAN); 
short result = ((short) (buffer.get() & 0xff)); 

ロング

ByteBuffer buffer = ByteBuffer.wrap(input); 
buffer.order(ByteOrder.BIG_ENDIAN); 
long result = ((long) buffer.getInt() & 0xffffffffL); 

のInt

ByteBuffer buffer = ByteBuffer.wrap(input); 
buffer.order(ByteOrder.BIG_ENDIAN); 
int result = (buffer.getShort() & 0xffff); 

文字列

String result = new String(removeStringGarbage(input), Charset.forName("US-ASCII")); 

これは素晴らしい動作します。私の質問は、どのように私は逆を行い、オブジェクトを正しいサイズのバイトバッファに入れてUDPで返送するのですか?

+1

"UDPからJavaに変換するには、 " - 代わりにByteBufferを読み出すだけではないのですか?安くて読みやすい。 – chrylis

+0

申し訳ありませんが、 "msg"という変数が入ってくるバイトバッファです。 – Tacitus86

+0

バイトバッファまたはByteBuffer?後者の場合は、 'getShort()'やそれ以外のものを使うことができます。 – chrylis

答えて

0

既存のオンザフライバイナリ形式に正確に従わなければならない場合は、「Kaitai Struct」(http://kaitai.io/)を試してみてください。

あなたは(つまり、あなたがそれを制御している)あなたのシリアル化形式を変更するには余裕がある場合は、「プロトコルバッファ」を見てみましょう:どちらの場合もhttps://developers.google.com/protocol-buffers/docs/javatutorial

を、既存のライブラリを使用するには、へ宣言的にバイナリプロトコルを記述して、多くの時間と労力を費やすことなく、 となり、通常はより堅牢なコードになります(コード生成者が壊れたデータをより良く処理し、誤植をしないようにする)。

"プロトコルバッファ"では、拡張性も得られます。つまり、下位互換性を維持しながらプロトコルを進化させることができます。

あなたはまだシリアライズ/手動でデータをデシリアライズしたい場合は、 次のようにちょうどのByteBufferのputXメソッドを使用します。

buffer.put((byte)(type & 0xFF)); 
buffer.put((byte)(flags & 0xFF)); 
buffer.putShort((short)(len & 0xFFFF)); 
buffer.putInt((int)(sequenceN & 0xFFFFFFFF)); 
buffer.putShort((short)(startIdx & 0xFFFF)); 
buffer.putShort((short)(endIdx & 0xFFFF)); 

入れ操作タイプ(すなわち、入れ(バイナリフィールドのサイズと一致する必要があります)、UINT16のputShort、UINT32のputInt、UINT32のputIntなど)、適切なマスクを適用する必要があります(0xFFのように0xFFFFなど)

+1

He *は、既存のワイヤプロトコルに厳密に従っています。それは質問で指定されています。 – EJP

+0

あなたはおそらくそれで正しいでしょう(私は最初に "クライアントサーバー"と混同され、OPがワイヤエンコーディングを制御していると暗示しました)。 私はそれに応じて私の答えを再構築しました。 – zeppelin

+0

ありがとうzeppelin。変換する方法(サイズダウン)を把握するだけです。私は、uint *からJavaオブジェクトへのサイズを増やさなければなりませんでした。だから私はショート - > uint8、Int - > uint16、long - > uint32に行く必要があります。何か案は? – Tacitus86

関連する問題