【发布时间】:2026-02-09 06:55:02
【问题描述】:
我正在尝试使用 C# TCPClient 类将我的笔记本电脑与我的独立电脑连接。
笔记本电脑正在运行一个简单的控制台应用程序并扮演服务器的角色。
PC 是 Unity 应用程序(2018.1.6f1 with .Net4.x Mono)
发送代码是
public void SendData() {
Debug.Log("Sending data");
NetworkStream ns = client.GetStream();
BinaryFormatter bf = new BinaryFormatter();
TCPData data = new TCPData(true);
using (MemoryStream ms = new MemoryStream()) {
bf.Serialize(ms, data);
byte[] bytes = ms.ToArray();
ns.Write(bytes, 0, bytes.Length);
}
}
在笔记本电脑的项目中使用相同的代码,除了Debug.Log()被Console.WriteLine()替换
我使用数据接收
public TCPData ReceiveData() {
Debug.Log("Waiting for Data");
using (MemoryStream ms = new MemoryStream()) {
byte[] buffer = new byte[2048];
int i = stream.Read(buffer, 0, buffer.Length);
stream.Flush();
ms.Write(buffer, 0, buffer.Length);
ms.Seek(0, SeekOrigin.Begin);
BinaryFormatter bf = new BinaryFormatter();
bf.Binder = new CustomBinder();
TCPData receivedData = (TCPData)bf.Deserialize(ms);
Debug.Log("Got the data");
foreach (string s in receivedData.stuff) {
Debug.Log(s);
}
return receivedData;
}
}
两边都一样,
我尝试传输的数据如下所示
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct TCPData {
public TCPData(bool predefined) {
stuff = new string[2] { "Hello", "World" };
ints = new List<int>() {
0,1,2,3,4,5,6,7,8,9
};
}
public string[] stuff;
public List<int> ints;
}
自定义活页夹来自here 没有它我会得到一个装配错误
我得到Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
现在的问题:
将此从 PC 发送到笔记本电脑 - 100% 成功率
将此从笔记本电脑发送到 PC - 20% 的成功率
(80% 是上述例外)
它“有时”怎么可能起作用?
不应该是 100% 还是 0% 吗?
如何让它工作?
谢谢
E:好的,感谢所有建议,我设法增加了成功的机会,但它仍然偶尔会失败。
我发送的数据大小“数据包”有 80% 的时间正确接收,但在某些情况下,与发送的 ~500 相比,我从 byte[] 得到的数字是 3096224743817216(非常大)。
我使用的是 Int64 数据类型。
E2:在 E1 中我分别发送数据长度数据包,现在我将它们合并,这确实正确解释了长度,但现在我无法反序列化数据......每次我收到The input stream is not a valid binary format. The starting contents (in bytes) are: 00-00-00-00-00-00-04-07-54-43-50-44-61-74-61-02-00 ...
我从流中读取前 8 个字节,剩下的“x”是数据,在服务器上反序列化它,反序列化相同的数据抛出。
E3:通过重写流处理代码来修复它,我在那里的某个地方犯了一个错误;)
【问题讨论】:
-
您是把
TCPData放在它自己的文件中还是放在另一个.cs 文件中?这在 Unity 中很重要 -
@Programmer 是的,我做到了,但这真的很重要,因为网络与 Unity 无关吗? (这里有 Unity 标签,以防 .net 框架版本与它有关)
-
最有可能的是从 PC 到笔记本电脑的数据作为单个数据报发送,而相反的数据被拆分为多个数据报。问题是接收端如何知道数据的末尾在哪里。为了证明我的观点,在反序列化之前检查接收到的字节数
-
@jdweng 总计 543 个字节,我收到 536 个,然后是剩下的 7 个 .. 这 7 个字节有时会出现在第一个“批次”中,这是否是 ~20% 成功的原因?感谢您为我指明方向;)
-
正如我所说,TCP 允许路由器和服务器随机拆分数据报。您需要在消息的开头添加一个字节数,然后在收到时读取,直到获得所有字节。
标签: c# unity3d serialization tcpclient networkstream