2012-11-01 36 views
3

问题“StreamCorruptedException:无效的流头”当读取的ObjectInputStream从C#客户端发送

我试图发送从C#客户端的protobuf消息,该Java服务器,但我得到这个异常:

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="[email protected]"; 
    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()); 
     } 


    } 
+1

Java的ObjectInputStream可能仅适用于java-java通信。为了让C#与Java交谈,您需要一个平台中立的协议。 – irreputable

+2

@ Kaiser4you消息是如何产生的?它是如何写入插座?一种可能性是你真的已经损坏了它。 –

+0

@MarcGravell它被写成一个字节数组。我可以使用ObjectInputStream与C#客户端? – Kaiser4you

回答

5

tldr;问题是使用ObjectInputStream (Java)其中只能工作ObjectOutputStream (Java)生成的数据。在这种情况下StreamCorruptedException正在生成,因为该流正在给出无效数据是而不是ObjectOutputStream (Java)生成。使用DataInputStream (Java)来读取BinaryWriter (C#)生成的数据。这两个只支持“原始”类型。只要正确endianessusedsign stuffing是根据需要进行:整数,浮点数,双打(但不是小数),和字节数组可以安全地发送这种方式。

ObjectInputStream (Java)

的ObjectInputStream的反序列化基元数据和使用ObjectOutputStream [用Java]先前写入对象。

DataInputSteam (Java)

的数据输入流允许应用程序读取基本[..]类型从底层输入流 ..

BinaryWriter (C#)

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


注:

  • DataInputSteam (Java) is big-endian,但BinaryWriter (C#) must be converted to big-endian
  • 没有问题(除了字节序)转移char/charactershortintlongfloatdouble数据类型时,因为他们在C#和Java一样签署性质和位表示。
  • byte (Java, signed) vs byte (C#, unsigned)可能会出现签名问题。谢天谢地,ProtocolBuffer将自动处理此,如果给予适当的byte[] (Java or C#)
  • 字符串可以提供额外的乐趣,由于轻微的编码差异。
0
使用本C#的OutputStream方法和 DataInputStream所(爪哇),而不是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()); 
     } 

    } 

所以:

我得到EndianBinaryWriterEndianBitConverterMiscUtil

相关问题