使用二进制序列化程序进行C#TCP数据传输
我正在尝试使用C#TCPClient类将我的笔记本电脑与我的单机电脑连接起来 膝上型电脑运行一个简单的控制台应用程序,扮演服务器的角色 PC是一款统一应用程序(2018.1.6f1和.Net4.x Mono) 发送的代码是使用二进制序列化程序进行C#TCP数据传输,c#,unity3d,serialization,tcpclient,networkstream,C#,Unity3d,Serialization,Tcpclient,Networkstream,我正在尝试使用C#TCPClient类将我的笔记本电脑与我的单机电脑连接起来 膝上型电脑运行一个简单的控制台应用程序,扮演服务器的角色 PC是一款统一应用程序(2018.1.6f1和.Net4.x Mono) 发送的代码是 public void SendData() { Debug.Log("Sending data"); NetworkStream ns = client.GetStream(); BinaryFormatter bf = new BinaryForm
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;
}
[可序列化,结构布局(LayoutKind.Sequential)]
公共结构TCPData{
公共TCPData(bool预定义){
stuff=新字符串[2]{“Hello”,“World”};
ints=新列表(){
0,1,2,3,4,5,6,7,8,9
};
}
公共字符串[]东西;
公开名单;
}
定制活页夹来自
没有它,我会得到一个汇编错误
使用它,我得到二进制流“0”不包含有效的BinaryHeader。可能的原因是序列化和反序列化之间的无效流或对象版本更改。
现在的问题是:
将此信息从PC发送到笔记本电脑-100%成功率
将此从笔记本电脑发送到PC-20%的成功率
(80%是上述例外)
它“有时”怎么可能起作用呢?
应该是100%还是0%?
我如何让它工作?
谢谢
E:好的,感谢所有的建议,我设法增加了成功的机会,但偶尔还是失败了
我发送了一个数据大小的“数据包”,它在正确接收的时间中占80%,但在某些情况下,我从字节[]得到的数字是3096224743817216(大得离谱),而发送的是500
我使用的是Int64数据类型
E2:在E1中,我单独发送数据长度数据包,现在我将它们合并,这确实正确解释了长度,但现在我无法反序列化数据。。。每次我得到时,输入流都不是有效的二进制格式。起始内容(以字节为单位)为:00-00-00-00-00-00-04-07-54-43-50-44-61-74-61-02-00…
我从流中读取前8个字节,剩余的“x”是数据,在服务器上反序列化,反序列化相同的数据抛出
E3:通过重写流处理代码修复了它,我在其中的某个地方犯了一个错误;) 在读取请求的字节数之前不会阻塞:
“此方法将数据读入缓冲区参数,并返回成功读取的字节数。如果没有可读取的数据,Read方法返回0。读取操作读取尽可能多的可用数据,最大读取量为size参数指定的字节数。如果远程主机关闭连接,并且已收到所有可用数据,则读取方法将立即完成并返回零字节。”
你必须
1) 知道需要多少字节
及
2) 在Read()上循环,直到收到预期的字节
如果您使用更高级别的协议,如HTTP或Web套接字,它们将处理此“消息帧”“给你。如果您直接在TCP/IP上编码,那么这就是您的责任。您是将TCPData
放在它自己的文件中还是另一个.cs文件中?这在我看来很重要Unity@Programmer是的,我有,但这真的很重要,因为网络与团结无关?(Unity标签在这里只是为了以防万一.net framework版本与此有关)最有可能的情况是,从PC到笔记本电脑的数据以单个数据报的形式发送,而相反的方向是将数据拆分为多个数据报。问题是接收端如何知道数据的结尾在哪里。要证明我的观点,请检查de之前接收的字节数-serializing@jdweng总共543字节,我收到536字节,然后是剩余的7。。这就是为什么这7个字节有时会在第一批中得到20%的成功?谢谢你为我指点方向;)正如我所说,TCP允许路由器和服务器随机分割数据报。您需要在消息的开头添加一个字节计数,然后在接收时读取,直到获得所有字节。因此,正在发生的情况是:一方从总计“y”中发送“x”数量的数据,另一方会立即使用这些字节并返回,因为它没有其他东西可以接收,最后在发送完剩余的字节后,这些字节实际上会丢失吗?为什么它不能只对一方起作用?这是我第一次玩网络游戏。Read()中通常会有非常小的消息不会被打断,因此方向之间的消息大小差异可以解释这一点,但也可能取决于其他因素。