3

問題

C#クライアントからこのJavaサーバーにprotobufメッセージを送信しようとしていますが、次の例外が発生します。

java.io.StreamCorruptedException: invalid stream header: 0A290A08 
java.io.StreamCorruptedException: invalid stream header: 0A290A08
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)

正直言って少し戸惑っています。どんな助けでも大歓迎です。ありがとう!

  • Javaサーバー
    public ControllerThread(Socket s){
    this.s = s; try {

        this.objectInputStream = new ObjectInputStream(s.getInputStream());
        byte size = objectInputStream.readByte();System.out.println("Server: BYTES SIZE:" +     size);
        byte[] bytes = new byte[size];
        objectInputStream.readFully(bytes);
        AddressBook adb = AddressBook.parseFrom(bytes);
        System.out.println("Server: Addressbook:" + adb.getPersonCount());

    } catch (IOException e) { 
        System.out.println("Server: BufferedReader oder PrintWriter von ThermoClient konnte nicht erstellt werden");
        e.printStackTrace(); } 
        } }

C#コード

public AddressBook InitializeAdressBook()
{
    Person newContact = new Person();

    AddressBook addressBookBuilder = new AddressBook();
    Person john = new Person();
    //john.id=1234;
    john.name="John Doe";
    john.email="jdoe@example.com";
    Person.PhoneNumber nr = new Person.PhoneNumber();
    nr.number="5554321";
    john.phone.Add(nr);
    addressBookBuilder.person.Add(john);
    TextBox.Text += ("Client: Initialisiert? " + addressBookBuilder.ToString()) + "\t" + "\n";
    TextBox.Text += " Erster Person " + addressBookBuilder.person.First().name + "\t" + "\n";

    return addressBookBuilder; 
}

c#OutputStream

    public void SendMessage(Stream ns, byte[] msg)
    {
        byte size = (byte)msg.Length;

        try
        {
            ns.WriteByte(size);
            ns.Write(msg, 0, msg.Length);
            ns.Flush();
            ns.Close();
        }
        catch (ArgumentNullException ane)
        {
            TextBox.Text += "ArgumentNullException : {0}" + ane.ToString();
        }
        catch (Exception e)
        {
            TextBox.Text += ("Unexpected exception : {0}" + e.ToString());
        }


    }
4

2 に答える 2

7

tldr; 問題は、によって生成されたデータObjectInputStream (Java)のみ機能ObjectOutputStream (Java)するを使用することです。この場合、StreamCorruptedExceptionストリームにはによって生成されなかった無効なデータが与えられているため、が生成されます。ObjectOutputStream (Java)

代わりに、を使用DataInputStream (Java)してによって生成されたデータを読み取りますBinaryWriter (C#)。これらは両方とも「プリミティブ」タイプのみをサポートします。正しいエンディアン使用され、必要に応じて符号の詰め込みが実行される限り、整数、浮動小数点数、倍精度浮動小数点数(10進数は除く)、およびバイト配列をこの方法で安全に送信できます。

ObjectInputStream (Java)

ObjectInputStreamは、[Javaで]ObjectOutputStreamを使用して以前に書き込まれたプリミティブデータとオブジェクトを逆シリアル化します。

DataInputSteam (Java)

データ入力ストリームにより、アプリケーションは、基になる入力ストリームからプリミティブ[..]型を読み取ることができます。

BinaryWriter (C#)

プリミティブ型をバイナリでストリームに書き込み、特定のエンコーディングでの文字列の書き込みをサポートします。


ノート:

  • DataInputSteam(Java)はビッグエンディアンですが、BinaryWriter(C#)はビッグエンディアンに変換する必要があります
  • 、、、、、、およびデータ型を転送する場合char/character、C#とJavaで同じ符号付きの性質とビット単位の表現があるため、short(エンディアンを除いて)問題はありません。intlongfloatdouble
  • 署名された問題は、byte (Java, signed)vsに対して発生する可能性がありbyte (C#, unsigned)ます。ありがたいことに、適切なが与えられた場合、 ProtocolBufferはこれを自動的に処理byte[] (Java or C#)します。
  • 文字列は、エンコーディングのわずかな違いにより、さらに楽しいものを提供できます。
于 2012-11-02T20:24:13.947 に答える
0

したがって、このc#OutputStreamメソッドとDataInputStream(Java)の代わりにObjectOutputSteamを使用すると、問題なく機能します。

 public void SendEndianBinaryMsg(Stream ns, byte[] msg)
    {
        byte size = (byte)msg.Length;

        try
        {

            EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Big, ns);
            writer.Write(size); 
            writer.Write(msg); 
            writer.Flush();
            ns.Close();
        }
        catch (ArgumentNullException ane)
        {
            TextBox.Text += "ArgumentNullException : {0}" + ane.ToString();
        }
        catch (Exception e)
        {
            TextBox.Text += ("Unexpected exception : {0}" + e.ToString());
        }

    }

ノート:

MiscUtilからEndianBinaryWriterとEndianBitConverterを取得します

于 2012-11-06T18:19:50.450 に答える