2012-11-01 85 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

相關問題