我正在尝试使用C#TCPClient类将笔记本电脑与独立PC连接起来。
笔记本电脑正在运行一个简单的控制台应用程序,并扮演服务器的角色。
PC是Unity应用程序(带有.Net4.x Mono的2018.1.6f1)
发送代码是
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%,但是在某些情况下,我从byte []获得的数字是3096224743817216(非常大),与发送的〜500相比。
我正在使用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:通过重写流处理代码对其进行了修复,我在其中的某个地方犯了一个错误;)
答案 0 :(得分:1)
NetworkStream.Read()在读取请求的字节数之前不会阻塞:
“此方法将数据读入buffer参数并返回成功读取的字节数。如果没有可读取的数据,则Read方法将返回0。Read操作将读取尽可能多的数据,最多大小由size参数指定。如果远程主机关闭连接,并且已收到所有可用数据,则Read方法立即完成并返回零字节。”
您必须
1)知道您期望多少字节
和
2)在Read()上循环,直到收到所需的字节为止。
如果您使用HTTP或Web套接字等高级协议,它们将为您处理此“消息框架”。如果您直接在TCP / IP上编码,那是您的责任。