使用 BinarySerializer 的 C# TCP 数据传输

C# TCP data transfer with BinarySerializer

我正在尝试使用 C# TCPClient class.

将我的笔记本电脑连接到我的独立 pc

笔记本电脑是运行一个简单的控制台应用程序,扮演着服务器的角色。

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);
    }
}

Laptop 项目中使用相同的代码,只是 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% 是上面的例外)

它 "sometimes" 怎么可能起作用?
不应该是 100% 或 0% 吗?
我如何让它工作?

谢谢

E: 好的,感谢所有的建议,我设法增加了成功的机会,但它仍然偶尔会失败。

我发送了一个数据大小 "packet",这是 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:通过重写流处理代码修复了它,我在某处犯了一个错误;)

NetworkStream.Read() 在读取请求的字节数之前不会阻塞:

"This method reads data into the buffer parameter and returns the number of bytes successfully read. If no data is available for reading, the Read method returns 0. The Read operation reads as much data as is available, up to the number of bytes specified by the size parameter. If the remote host shuts down the connection, and all available data has been received, the Read method completes immediately and return zero bytes."

你必须

1) 了解您期望的字节数

2) 在 Read() 上循环,直到收到预期的字节。

如果您使用更高级的协议,如 HTTP 或 Web Sockets,他们会为您处理 "message framing"。如果您直接在 TCP/IP 上编码,那是您的责任。