java 读取从 C# 客户端发送的 ObjectInputStream 时出现“StreamCorruptedException: invalid stream header”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13186848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"StreamCorruptedException: invalid stream header" when reading ObjectInputStream sent from C# client
提问by Kaiser4you
Problem
问题
I'm trying to send a protobuf message from a C# client to this Java Server but I get this exception:
我正在尝试从 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)
I'm a bit at a loss to be honest. Any help is appreciated. Thanks!
老实说,我有点不知所措。任何帮助表示赞赏。谢谢!
- Java server
- 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# code
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
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());
}
}
回答by
tldr;The problem is using ObjectInputStream (Java)
which only workswith data generated by ObjectOutputStream (Java)
. In this case the StreamCorruptedException
is being generated because the stream is being given invaliddata that was notgenerated by ObjectOutputStream (Java)
.
tldr; 问题是使用ObjectInputStream (Java)
which仅适用于ObjectOutputStream (Java)
. 在这种情况下,StreamCorruptedException
正在生成 ,因为流被赋予了不是由 生成的无效数据。ObjectOutputStream (Java)
Instead, use DataInputStream (Java)
to read the data generated by BinaryWriter (C#)
. Both of these only support "primitive" types. As long as the correct endianessis usedand sign stuffingis performed as needed: integers, floats, doubles (but not Decimals), and byte arrays can be safely sent this way.
相反,使用DataInputStream (Java)
读取由 生成的数据BinaryWriter (C#)
。这两者都只支持“原始”类型。只要正确字节序的使用和符号堆砌如需要进行:整数,浮点数,双打(但不是小数),和字节数组可以安全地发送这种方式。
An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream [in Java].
ObjectInputStream 反序列化之前使用 ObjectOutputStream [在 Java 中] 编写的原始数据和对象。
A data input stream lets an application read primitive [..] typesfrom an underlying input stream ..
数据输入流允许应用程序从底层输入流读取原始 [..] 类型..
Writes primitive typesin binary to a stream and supports writing strings in a specific encoding.
将二进制原始类型写入流,并支持以特定编码写入字符串。
Notes:
笔记:
- DataInputSteam (Java) is big-endian, but BinaryWriter (C#) must be converted to big-endian.
- There are no issues (aside from endianness) when transferring the
char/character
,short
,int
,long
,float
, anddouble
data-types as they have the same signed nature and bitwise representation in C# and Java. - Signed problems can arise for
byte (Java, signed)
vsbyte (C#, unsigned)
. Thankfully, ProtocolBuffer will automatically handle thisif given the appropriatebyte[] (Java or C#)
. - Strings can provide additional fun due to slight encoding differences.
- DataInputSteam (Java) 是 big-endian,但BinaryWriter (C#) 必须转换为 big-endian。
- 传输, , , , 和数据类型时没有问题(除了字节序)
char/character
,因为它们在 C# 和 Java 中具有相同的有符号性质和按位表示。short
int
long
float
double
byte (Java, signed)
vs可能会出现签名问题byte (C#, unsigned)
。值得庆幸的是,ProtocolBuffer会自动处理,如果给予适当的byte[] (Java or C#)
。- 由于轻微的编码差异,字符串可以提供额外的乐趣。
回答by Kaiser4you
So with this c# OutputStream method and DataInputStream( Java) instead ObjectOutputSteam it works without any problems
因此,使用此 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());
}
}
Notes:
笔记:
I get EndianBinaryWriterand EndianBitConverterfrom MiscUtil.
我从MiscUtil得到EndianBinaryWriter和EndianBitConverter。