C# Networkstream.Write()阻塞问题

C# Networkstream.Write()阻塞问题,c#,networkstream,C#,Networkstream,我目前正在测试一个我编写的托管c#网络库,偶尔会遇到一个问题。此问题表现为networkstream.write()上的5000ms块非常一致(始终在30ms内),可能占所有发送操作的1%。这是在一个测试环境中,都在本地运行,每次使用完全相同的数据包大小(2MB)。在客户端,我不断地向连接的网络流写入以下内容: tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length); tcpClientNetworkStream.Writ

我目前正在测试一个我编写的托管c#网络库,偶尔会遇到一个问题。此问题表现为networkstream.write()上的5000ms块非常一致(始终在30ms内),可能占所有发送操作的1%。这是在一个测试环境中,都在本地运行,每次使用完全相同的数据包大小(2MB)。在客户端,我不断地向连接的网络流写入以下内容:

tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length);
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length);
在服务器端,我使用异步读取等待数据。一旦数据出现,我就在tcpClientNetworkStream.DataAvailable上使用while循环,直到收到所有数据

我知道networkstream.write()可能会在缓冲区已满时阻塞,但如果这是一个问题,我想不出在服务器端更快地清除缓冲区的方法(发送和接收缓冲区大小默认为8192字节)。区块如此一致的事实似乎很奇怪。我的第一个想法可能是某种形式的线程。睡眠,但做一个完整的项目搜索显示没有。如果有人能帮助阐明这个问题,我们将不胜感激

马克

编辑添加:一个似乎使问题消失的黑客行为如下(尽管由于区块复制存在相关的性能影响):

edittoadd2:我还通过使用两个异步写操作重现了这个问题,两个异步写操作之间有一个线程信号。目前,我唯一的解决方案是上述编辑中的单写操作

编辑到add3:好的,下面是另一个可能的修复。我仍然有兴趣知道为什么连续写入有时会以这种方式“阻塞”

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

编辑到添加4:经过进一步的广泛测试,“编辑到添加3”中的解决方案并没有解决问题,它只是将发送次数减少到大约0.1%。好得多,但远未解决。接下来,我将用块读替换异步读,看看是否按照PaulF的建议对其进行排序。

好的,这个问题没有具体的答案,所以我将尽我所能自己给出一个小结论。我最好的猜测是,这个问题最初是因为我填充tcp缓冲区的速度比清除它的速度快。如果缓冲区已满,则在尝试添加更多数据之前会有未知的等待时间。当在同一台机器内发送和接收数据时,这个问题可能最为明显。重要的是要记住.NET中的默认读缓冲区大小只有8192个字节,所以如果写得更大,可能会考虑把这个读缓冲区的大小增加到更大一些,比如512000个字节。然而,由于对象堆太大等原因,这本身会导致其他问题,但这可能是对另一个问题的讨论。

请发布更多代码,比如数据字节从何而来?是否在某个地方进行了缓冲?我将一个数据包对象传递给一个SendPacket()方法,该方法包含上述NetworkStream.Write()方法。一旦在SendPacket()之外创建了此数据包对象,它就包含“headerBytes”和“dataBytes”的字节数组。我很想知道,如果在服务器端使用同步(阻塞)读取,问题是否仍然存在。PaulF提到了它。。。但问题是否真的发生在服务器的读取端。。。你这里没有那个代码。我猜你正在经历愚蠢的窗口综合症。MS为其提供了一个修复程序,解决了一些场景:。
BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream);
sendStream.Write(bytesToSend, 0, bytesToSend.Length);
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length);
sendStream.Flush();