简体   繁体   English

Networkstream.Write()阻塞问题

[英]Networkstream.Write() Blocking Problem

I'm currently testing a managed c# network library I've written and I've come up against an occasional problem. 我目前正在测试我编写的托管c#网络库,我遇到了偶然的问题。 This problem manifests as a very consistent (always within 30ms) 5000ms block on networkstream.write() for perhaps 1% of all send operations. 这个问题在networkstream.write()上显示为非常一致(总是在30ms内)5000ms块,可能占所有发送操作的1%。 This is in a test environment, all running locally, using the exact same packet size (2MB) each time. 这是在测试环境中,全部在本地运行,每次使用完全相同的数据包大小(2MB)。 On the client end I continuously write the following to a connected networkstream: 在客户端,我不断将以下内容写入连接的网络流:

tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length);
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length);

and on the server end I use an asynchronous read waiting for data. 在服务器端,我使用异步读取等待数据。 Once data appears I use a while loop over tcpClientNetworkStream.DataAvailable until all data has been received. 一旦数据出现,我在tcpClientNetworkStream.DataAvailable上使用while循环,直到收到所有数据。

I am aware that networkstream.write() can block if the buffers are full but if this is the problem I can't think of a quicker way of clearing them at the server end (Send and Receive buffer sizes are default at 8192 bytes). 我知道如果缓冲区已满,networkstream.write()可以阻塞,但如果这是问题,我想不出更快的方法在服务器端清除它们(发送和接收缓冲区大小默认为8192字节) 。 The fact the block is so consistent seems very odd. 块如此一致的事实似乎很奇怪。 My first thought was possibly some form of Thread.Sleep but doing a full project search shows none. 我的第一个想法可能是某种形式的Thread.Sleep但是进行完整的项目搜索没有显示。 If anyone could help shed some light on this issue that would be greatly appreciated. 如果有人能帮助阐明这个问题,那将非常感激。

Marc

edit to add: A hack which seems to make the problem go away is the following (although there is an associated performance hit due to the BlockCopy): 编辑添加:一个似乎让问题消失的黑客攻击如下(尽管由于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);

edit to add2: I've also reproduced the problem by using two asynchronous writes with a thread signal between the two. 编辑add2:我也通过使用两个异步写入和两者之间的线程信号来重现问题。 At the moment the only solution I have is the single write operation as in the above edit. 目前我唯一的解决方案就是上面编辑中的单一写操作。

edit to add3: Ok, another possible fix follows. 编辑add3:好的,另一个可能的修复如下。 I'm still interested to know why the successive write occasionally 'blocks' in the way it does. 我仍然有兴趣知道为什么连续写它会像它一样“阻塞”。

BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream);
sendStream.Write(bytesToSend, 0, bytesToSend.Length);
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length);
sendStream.Flush();

edit to add4: After further extensive testing the solution in 'edit to add3' does not make the problem go away, it just reduces the occurrence to about 0.1% of sends. 编辑add4:经过进一步的广泛测试后,'edit to add3'中的解决方案不会使问题消失,只会将发生率降低到约0.1%。 Much better but far from solved. 好多了但远没有解决。 I will be replacing the asynchronous read with a blocking read next to see if that sorts it, as suggested by PaulF. 我将使用阻塞读取替换异步读取,然后查看是否对其进行排序,如PaulF所建议的那样。

Ok, no specific answers to this question so I will do my best to provide a little conclusion myself. 好的,这个问题没有具体的答案,所以我会尽我所能提供一些结论。 My best guess is that this problem was originally caused because I was filling the tcp buffer faster than I was clearing it. 我最好的猜测是这个问题最初是因为我填充tcp缓冲区比清除它更快。 If the buffer is filled there is some unknown wait time before attempting to add more data. 如果缓冲区已填满,则在尝试添加更多数据之前会有一些未知的等待时间。 This problem would perhaps be most apparent when sending and receiving data within the same machine. 在同一台机器内发送和接收数据时,这个问题可能最为明显。 It's important to remember that the default read buffer size in .net is only 8192 bytes, so if writing in much larger chunks, perhaps consider increasing this read buffer size to something larger such as 512000 bytes. 重要的是要记住.net中的默认读取缓冲区大小仅为8192字节,因此如果写入更大的块,可能会考虑将此读取缓冲区大小增加到更大的值,例如512000字节。 However this in itself causes other issues due to the large object heap etc but that is potentially discussion to a different question. 然而,由于大对象堆等,这本身会导致其他问题,但这可能会讨论另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM