クライアントからサーバーにデータを送信しようとしています。どちらのアプリケーションもjavaで書かれています。しかし、SWIGラッパーよりもC++で実装されたtlsレイヤーを使用しています。 tls層は、クライアントからの文字列を受け取り、それをサーバー側に送信し、Javaサーバーアプリケーションに通知します(そして文字列を渡します)。ただし、この文字列にはシリアルデータが含まれている必要があります。どういうわけか私はprotobufを使ってデータをシリアライズするのに苦労しています。私はToDoListMessage
という名前のjava protobufクラスを使いたいと思います。いるProtobufは次のようになります。長い文字列のprotobufでの異常な動作
message ToDoListMessage{
optional string user = 1;
optional string token = 2;
}
しかし、生成されたJavaクラスは、それが前にシリアライズデータ解析に失敗:
com.google.protobuf.InvalidProtocolBufferException:プロトコルメッセージ タグが無効なワイヤータイプを持っていたが。
現在、サーバーにデータを送信していません。ただ、シリアル化をテストし、クライアント側に一部を解析:私が試した何
[10, 4, 116, 101, 115, 116, 18, 14, 51, 56, 54, 51, 50, 55, 51, 53, 55, 50, 50, 55, 53, 53]
:
ToDoListMessageProto msg = ToDoListMessageProto.newBuilder().setUser("test").setToken("38632735722755").build();
byte b [] = msg.toByteArray();
String sMsg = Arrays.toString(b);
System.out.println("send message = " + sMsg);
ToDoListMessageProto outputmessage;
outputmessage = ToDoListMessageProto.parseFrom(sMsg.getBytes());
は、メッセージは次のようになります
1)私がこれまでに見つかったすべてのソリューションは、この問題を言いますCodedOutputStream
を使用して解決できます。しかし、tlsレイヤーはストリームではなく、ストリングを期待しています。
ByteArrayOutputStream bos = new ByteArrayOutputStream();
CodedOutputStream cos = CodedOutputStream.newInstance(bos);
msg.writeTo(cos);
cos.flush();
byte b [] = msg.toByteArray();
String sMsg = Arrays.toString(b);
をしかし、私は、この解析のために上記と同じエラーを取得:しかし、私はまた、次のように試してみました
CodedInputStream cis = CodedInputStream.newInstance(sMsg.getBytes());
ToDoListMessageProto message = ToDoListMessageProto.parseFrom(cis);
2)また、私はUTF8エンコードされた文字列の代わりに、配列のように使用してみましたone:
String sMsg = new String(b);
この場合、アプリはさらに奇妙な動作をします。短い「トークン」(例えば未満129ビット)の解析が動作しますが、長いトークンの失敗:com.google.protobuf.InvalidProtocolBufferException
: プロトコルメッセージを解析中に、入力が途中で予期せず終了 フィールドのこれは、入力が切り捨てられているか、または埋め込まれたメッセージが独自の長さを誤って報告した である可能性があります。
私は本当に理由を伝えることはできません。現在、トークンには数字のみが含まれています。
私はprotobufからシリアライズされた文字列をどのように得ることができますか?
この場合も、このテストにはtls転送はありません。現在、すべてのことがクライアント側で行われています。
更新:私はいるProtobufメッセージから直接バイト配列をフェッチするので
がエンコーディングを通過することは不可能です。私は、メッセージのtoByteString
方法もある見つかりましたが、この延ByteStringにtoStringUtf8
を使用すると、どちらも動作していないよう:
String sMsg = msg.toByteString().toStringUtf8();
System.out.println("send message = " + sMsg);
ToDoListMessageProto outputmessage;
outputmessage = ToDoListMessageProto.parseFrom(sMsg.getBytes());
私は私が長いか短いトークンを使用した場合と異なる同じエラーメッセージを(取得します、上記を参照)
単純に 'String'を使用せず、バイナリデータに' byte [] 'だけを使用してください。文字列はUnicodeを内部的に使用するため、エンコードおよびデコードのオーバーヘッドを節約できます。これはエラーが発生しやすくなります。 –
それはそれほど簡単ではありません。 C++側の配列を扱うとメモリ管理が要求されるためです。私がC++トラフjniからjavaにそのような配列を渡す場合、私は単にいつメモリを解放するのか知りません。それは多くの追加プログラミングを引き起こすでしょう。 –