读取从C#客户端发送的ObjectInputStream时出现"StreamCorruptedException:invalid stream header"

Kai*_*you 3 c# java stream

问题

我正在尝试从C#客户端向此Java Server发送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)
Run Code Online (Sandbox Code Playgroud)

说实话,我有点不知所措.任何帮助表示赞赏.谢谢!

  • 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(); } 
        } }
Run Code Online (Sandbox Code Playgroud)

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; 
}
Run Code Online (Sandbox Code Playgroud)

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());
        }


    }
Run Code Online (Sandbox Code Playgroud)

小智 7

tldr; 这个问题可以用ObjectInputStream (Java)只能由生成的数据ObjectOutputStream (Java).在这种情况下,StreamCorruptedException正在生成,因为流被赋予了生成的无效数据.ObjectOutputStream (Java)

相反,用于DataInputStream (Java)读取生成的数据BinaryWriter (C#).这两者都只支持"原始"类型.只要正确的字节顺序使用签署馅是根据需要进行:整数,浮点数,双打(但不是小数),和字节数组可以安全地发送这种方式.

ObjectInputStream (Java):

ObjectInputStream对先前使用ObjectOutputStream [在Java中]编写的原始数据和对象进行反序列化.

DataInputSteam (Java):

数据输入流允许应用程序从基础输入流中读取原语[..]类型.

BinaryWriter (C#):

二进制中的原始类型写入流并支持以特定编码写入字符串.


笔记:

  • DataInputSteam(Java)是big-endian,但BinaryWriter(C#)必须转换为big-endian.
  • 有没有问题(除了字节序)转移时char/character,short,int,long,float,和double数据类型,因为他们在C#和Java一样签署性质和位表示.
  • 可能出现的问题签署byte (Java, signed)VS byte (C#, unsigned).值得庆幸的是,如果给出合适的话,ProtocolBuffer会自动处理这个问题byte[] (Java or C#).
  • 由于轻微的编码差异,字符串可以提供额外的乐趣.