向网络管道写入大量数据时会丢失字节

本文关键字:字节 数据 管道 网络 | 更新日期: 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#对我说谎的事实。解决方法是以块的形式发送字节,并且不再谈论它。