Networkstream.Write()阻塞问题

本文关键字:问题 Write Networkstream | 更新日期: 2023-09-27 18:06:26

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

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

,在服务器端,我使用异步读取等待数据。一旦数据出现,我在tcpClientNetworkStream上使用while循环。数据在接收到所有数据之前可用。

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

Marc

编辑添加:一个似乎使问题消失的hack是以下的(虽然有一个相关的性能打击由于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:我还使用了两个异步写操作,两者之间有一个线程信号,从而重现了这个问题。目前,我唯一的解决方案是像上面的编辑一样进行单个写入操作。

edit to add3:好的,接下来是另一个可能的修复。我仍然很想知道为什么连续写入偶尔会"阻塞"。

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

edit to add4:经过进一步的广泛测试,edit to add3中的解决方案并没有使问题消失,它只是将发送的发生率减少到约0.1%。好多了,但还远没有解决。我将在旁边用阻塞读取替换异步读取,看看它是否排序,正如PaulF所建议的。

Networkstream.Write()阻塞问题

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