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# 输出流

    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)which仅适用ObjectOutputStream (Java). 在这种情况下,StreamCorruptedException正在生成 ,因为流被赋予了不是由 生成的无效数据。ObjectOutputStream (Java)

相反,用于DataInputStream (Java)读取由BinaryWriter (C#). 这两个都只支持“原始”类型。只要使用正确字节顺序并根据需要执行符号填充:整数、浮点数、双精度数(但不是小数)和字节数组都可以通过这种方式安全地发送。

ObjectInputStream (Java)

ObjectInputStream 反序列化以前使用 ObjectOutputStream [in Java] 编写的原始数据和对象。

DataInputSteam (Java)

数据输入流允许应用程序从底层输入流中读取原始 [..] 类型..

BinaryWriter (C#)

以二进制形式将原始类型写入流,并支持以特定编码写入字符串。


笔记:

  • DataInputSteam (Java) 是 big-endian,但BinaryWriter (C#) 必须转换为 big-endian
  • char/character传输、shortintlongfloat和数据类型时没有任何问题(除了字节顺序) ,double因为它们在 C# 和 Java 中具有相同的带符号性质和按位表示。
  • 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得到EndianBinaryWriterEndianBitConverter

于 2012-11-06T18:19:50.450 回答