我目前正在测试我编写的托管c#网络库,我遇到了偶然的问题.这个问题在networkstream.write()上显示为非常一致(总是在30ms内)5000ms块,可能占所有发送操作的1%.这是在测试环境中,全部在本地运行,每次使用完全相同的数据包大小(2MB).在客户端,我不断将以下内容写入连接的网络流:
tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length);
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length);
Run Code Online (Sandbox Code Playgroud)
在服务器端,我使用异步读取等待数据.一旦数据出现,我在tcpClientNetworkStream.DataAvailable上使用while循环,直到收到所有数据.
我知道如果缓冲区已满,networkstream.write()可能会阻塞,但如果这是问题我想不出更快的方法在服务器端清除它们(发送和接收缓冲区大小默认为8192字节) .块如此一致的事实似乎很奇怪.我的第一个想法可能是某种形式的Thread.Sleep但是进行完整的项目搜索没有显示.如果有人能帮助阐明这个问题,那将非常感激.
渣
编辑添加:一个似乎让问题消失的黑客攻击如下(尽管由于BlockCopy而导致相关的性能下降):
byte[] bytesToSend = new byte[headerBytes.Length + dataBytes.Length];
Buffer.BlockCopy(headerBytes, 0, bytesToSend, 0, headerBytes.Length);
Buffer.BlockCopy(dataBytes, 0, bytesToSend, headerBytes.Length, dataBytes.Length);
tcpClientNetworkStream.Write(bytesToSend, 0, bytesToSend.Length);
Run Code Online (Sandbox Code Playgroud)
编辑add2:我也通过使用两个异步写入和两者之间的线程信号来重现问题.目前我唯一的解决方案就是上面编辑中的单一写操作.
编辑add3:好的,另一个可能的修复如下.我仍然有兴趣知道为什么连续写它会像它一样"阻塞".
BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream);
sendStream.Write(bytesToSend, 0, bytesToSend.Length);
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length);
sendStream.Flush();
Run Code Online (Sandbox Code Playgroud)
编辑add4:经过进一步的广泛测试后,'edit to add3'中的解决方案不会使问题消失,只会将发生率降低到约0.1%.好多了但远没有解决.我将使用阻塞读取替换异步读取,然后查看是否对其进行排序,如PaulF所建议的那样.
好吧,这个问题没有具体的答案,所以我会尽力自己提供一个小结论。我最好的猜测是,这个问题最初是因为我填充 tcp 缓冲区的速度比清除它的速度快而引起的。如果缓冲区已满,则在尝试添加更多数据之前会有一些未知的等待时间。当在同一台机器内发送和接收数据时,这个问题可能最为明显。重要的是要记住,.net 中的默认读取缓冲区大小仅为 8192 字节,因此如果写入更大的块,也许可以考虑将此读取缓冲区大小增加到更大的值,例如 512000 字节。然而,由于大对象堆等,这本身会导致其他问题,但这可能是对不同问题的讨论。
| 归档时间: |
|
| 查看次数: |
2785 次 |
| 最近记录: |