【问题标题】:"StreamCorruptedException: invalid stream header" when reading ObjectInputStream sent from C# client读取从 C# 客户端发送的 ObjectInputStream 时出现“StreamCorruptedException:无效的流标头”
【发布时间】:2012-11-01 23:04:07
【问题描述】:

问题

我正在尝试从 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());
        }


    }

【问题讨论】:

  • Java 的 ObjectInputStream 可能只适用于 java-java 通信。要让 C# 与 Java 对话,您需要一个平台中立的协议。
  • @Kaiser4you 消息是如何生成的?它是如何写入套接字的?一种可能是你真的破坏了它。
  • @MarcGravell 它被写成一个字节数组。我可以将 ObjectInputStream 与 c# 客户端一起使用吗?
  • 请发布有用 C# 代码.. 将数据写入 到 C# 中适当的输出流的东西。此问题与 ProtocolBuffers 无关。请参阅错误消息。我试图通过包含一个适当的标题来帮助这个问题。 问题[报告]与ProtocolBuffers有关。尝试发送和接收“只是一个int”来查看。
  • 您发布的 c# 代码没有显示您如何将其放到套接字上。我很乐意提供帮助(protobuf 和 socket-servers 都非常熟悉),但是除非你能看到管道的两端,否则不可能诊断出不匹配。我正在寻找以下代码:a:序列化地址簿条目,b:添加长度前缀标头,以及 c:a 和 b 的输出如何放到原始套接字上。

标签: c# java stream


【解决方案1】:

tldr;问题在于使用ObjectInputStream (Java),它仅适用于ObjectOutputStream (Java) 生成的数据。在这种情况下,StreamCorruptedException 正在生成,因为该流被赋予 invalid 数据,而该数据不是ObjectOutputStream (Java) 生成的。

改为使用DataInputStream (Java) 读取BinaryWriter (C#) 生成的数据。这两个都只支持“原始”类型。只要正确的endianessused并且sign stuffing根据需要执行:整数、浮点数、双精度数(但不是小数)和字节数组都可以以这种方式安全地发送。

ObjectInputStream (Java):

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

DataInputSteam (Java):

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

BinaryWriter (C#):

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


注意事项:

  • DataInputSteam (Java) is big-endian,但是BinaryWriter (C#) must be converted to big-endian
  • 传输char/charactershortintlongfloatdouble 数据类型时没有任何问题(除了字节序),因为它们具有相同的签名性质和C# 和 Java 中的按位表示。
  • byte (Java, signed)byte (C#, unsigned) 可能会出现签名问题。值得庆幸的是,ProtocolBuffer 将自动处理此问题,如果提供适当的 byte[] (Java or C#)
  • 由于编码略有不同,字符串可以提供额外的乐趣。

【讨论】:

    【解决方案2】:

    所以用这个 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-06
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多