Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用二进制序列化程序进行C#TCP数据传输_C#_Unity3d_Serialization_Tcpclient_Networkstream - Fatal编程技术网

使用二进制序列化程序进行C#TCP数据传输

使用二进制序列化程序进行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

我正在尝试使用C#TCPClient类将我的笔记本电脑与我的单机电脑连接起来

膝上型电脑运行一个简单的控制台应用程序,扮演服务器的角色

PC是一款统一应用程序(2018.1.6f1和.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;
}
[可序列化,结构布局(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()中通常会有非常小的消息不会被打断,因此方向之间的消息大小差异可以解释这一点,但也可能取决于其他因素。