向网络管道写入大量数据时会丢失字节
本文关键字:字节 数据 管道 网络 | 更新日期: 2023-09-27 18:16:33
我想在两台计算机之间通过命名管道发送一些字节。客户端发送65537字节,PipeStream.Write()
返回,就好像这些字节已经发送了一样,但是服务器从来没有接收到这些字节。客户为什么要骗我?我想我可以以块的形式发送我的字节,但是在印象中PipeStream.Write
会为我做这件事。一台机器是虚拟的,一台是物理的。如果客户端少发送一个字节(65536字节),服务器将全部接收。在另一种情况下,两台机器都是物理的,所有65537字节也都可以正常接收。下面是重现该行为的代码。在一台机器上运行test.exe 100000 -
,在另一台机器上运行test.exe 65537 other.comp.name
:
class Program
{
const string PipeName = "TestPipe";
static void Main(string[] args)
{
int bufferSize = int.Parse(args[0]);
if (args[1] == "-")
{
using (var server = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 1,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
server.WaitForConnection();
byte[] result = new byte[bufferSize];
for (int offset = 0; offset < bufferSize; )
{
IAsyncResult asyncResult = server.BeginRead(result, offset, bufferSize - offset, null, null);
asyncResult.AsyncWaitHandle.WaitOne();
int bytesRead = server.EndRead(asyncResult);
if (bytesRead == 0)
{
Console.WriteLine("Client closed the pipe after {0} bytes.", offset);
return;
}
offset += bytesRead;
}
Console.WriteLine("All bytes are read.");
}
}
else
{
using (var client = new NamedPipeClientStream(args[1], PipeName, PipeDirection.InOut, PipeOptions.Asynchronous))
{
client.Connect(1000);
byte[] buffer = new byte[bufferSize];
client.Write(buffer, 0, buffer.Length);
client.WaitForPipeDrain();
Console.WriteLine("All bytes are written.");
}
}
}
}
您在PipeTransmissionMode.Byte
中使用管道。期望在这种模式下发送数据并完成处理。在这种情况下,在您的服务器代码中,您不应该在读取0字节时停止。相反,检查server.IsConnected
,一旦您的客户端关闭管道,这意味着所有的数据被发送,这个值变成false
。您可能会在中间得到一些bytesRead==0读数。
当涉及到64KB的VM限制时,我只是接受c#对我说谎的事实。解决方法是以块的形式发送字节,并且不再谈论它。