我在创建的异步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
答案 0 :(得分:1)
您的接收代码会在发布所有字节之前尝试读取。
当您尝试仅在一个软件包上发送大量数据时,您的readAsync将检测到要读取的内容,尝试读取可能无法使用的完整长度,并填充不是发布了0s
您可以在服务器上划分消息,在客户端上按部分阅读,也可以尝试阅读可用内容,直到您收到所有内容或已经过了一段时间