Networkstream.ReadAsync行为。校验和不匹配

时间:2014-04-08 15:24:01

标签: c# .net networking asynchronous protocols

我在创建的异步RSS提要聚合器应用程序中遇到了一个非常棘手的问题。

系统是从通信客户端和服务器构建的。服务器从不同的源收集RSS源项,然后根据订阅将它们分发给客户端。

我遇到的问题是 - 我的规范声明我必须实现一个预先定义的基于字节的协议,以便在客户端和服务器之间进行通信。该协议的一部分是当服务器向客户端发送有效载荷时,该有效载荷必须创建校验和并随之发送,然后当客户端接收到校验和时,校验和将根据接收的有效载荷进行等同。然后我们比较两个校验和,如果它们不匹配,那么我们就有问题了。

令我感到困惑的是,有时校验和将完全匹配,有时则不会,所有发送和接收操作使用相同的算法。

以下是检查传入的方法 - >

        private bool CheckChecksum(uint receivedChecksum, IEnumerable<byte> bytes) {
        uint ourChecksum = 0;
        foreach (var b in bytes)
            ourChecksum += b;
        if (ourChecksum != receivedChecksum) {
            Debug.WriteLine("received {0}, calculated {1}", receivedChecksum, ourChecksum);
            _writeOutToFile = true;
        }
        return receivedChecksum == ourChecksum;
    }

并在发送前计算 - >

        uint checksum = payloadBytes.Aggregate<byte, uint>(0,
            (currentChecksum, currentByte) => currentChecksum + currentByte);

由于行为似乎发生在具有非常大的校验和(通常为200万+)的更新上,因此我认为唯一可能导致它的是大字节[]大小。

正如您在上面所看到的,当校验和不匹配时,我会向文件写出有效负载的内容。我发现byte []只是提前结束(尽管读/写长度在客户端和服务器上都匹配)。字节[]的末尾只填充空格。

我正在使用NetworkStream.ReadAsync和WriteAsync来执行所有I / O操作。我认为这可能是我使用或理解这些方式的错误。

我意识到这是一个非常困难和模糊的问题(因为我不确定自己出了什么问题),但如果您需要任何进一步的信息,我会提供它。

以下是一些额外信息:

  • 校验和的类型为uint,它们的字节顺序在系统的两端都能正确编码。

  • Payloads是编码为ASCII字节并在客户端解码的字符串。

  • 所有消息都以校验和和有效负载长度发送。有效负载长度表示从流中读取的字节数。由于I读取来自网络流的有效负载长度字节数,当校验和不匹配时,有效负载在变化的长度后变为空白(但在此点之前是正确的)。

  • 有时(很少)校验和即使很大也会匹配。

  • 我在一台机器上本地运行客户端和服务器。

  • 我在阅读之前尝试过使用Thread.Sleep(5000),这没什么区别。

以下是发送和接收数据失败的示例。

从服务器发送 - http://pastebin.com/jvbCbQmJ

客户收到 - http://pastebin.com/eNkWymwi

1 个答案:

答案 0 :(得分:1)

您的接收代码会在发布所有字节之前尝试读取。

当您尝试仅在一个软件包上发送大量数据时,您的readAsync将检测到要读取的内容,尝试读取可能无法使用的完整长度,并填充不是发布了0s

您可以在服务器上划分消息,在客户端上按部分阅读,也可以尝试阅读可用内容,直到您收到所有内容或已经过了一段时间