在打开的 NamedPipeClientStream 上重新创建 UTF-8 StreamWriter 会导致服务器上出现额外的 BOM 字符

问题描述 投票:0回答:1

我有一个保持打开状态的

NamedPipeServerStream
,还有一个保持打开状态的
NamedPipeClientStream
NamedPipeServerStream
有一个保持打开状态的 UTF-8
StreamReader
NamedPipeClientStream
有一个 UTF-8
StreamWriter
,可以打开、写入一条消息、关闭然后重新打开以写入另一条消息。
StreamReader
StreamWriter
都是在
leaveOpen
标志设置为 true 的情况下打开的,因此
StreamWriter
在关闭时不会关闭
NamedPipeClientStream
。到目前为止,一切都很好。

我遇到一个问题,从第二次打开

StreamWriter
并发送消息时,
StreamReader
会读取额外的 BOM。我已经设法在一个小示例程序中重新创建它。它是用.NET 6构建的。这是示例程序的代码:

using System.IO.Pipes;

namespace NamedPipeTest
{
    internal class EncodingTest
    {
        private static NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("mypipe", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
        private static NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(".", "mypipe", PipeDirection.InOut, PipeOptions.Asynchronous);

        static void Main(string[] args)
        {
            Console.WriteLine("Hello! You are the client. Press any key to send a request.");

            Task[] tasks = new Task[]
            {
                Task.Run(() => Server()),
                Task.Run(() => Client())
            };

            Task.WaitAll(tasks);
        }

        static async Task Server()
        {
            if (!namedPipeServer.IsConnected)
            {
                namedPipeServer.WaitForConnection();
            }

            using (var reader = new StreamReader(namedPipeServer, System.Text.Encoding.UTF8, false, 1024, true))
            {
                while (true)
                {
                    string? line = await reader.ReadLineAsync();
                    Console.WriteLine($"Server: Received request: {line}");
                    if (!string.IsNullOrEmpty(line))
                    {
                        var lineBytes = System.Text.Encoding.UTF8.GetBytes(line);
                        var possibleBOMString = System.Text.Encoding.UTF8.GetString(new byte[] { lineBytes[0], lineBytes[1], lineBytes[2] });
                        if (possibleBOMString.Equals("\uFEFF"))
                        {
                            Console.WriteLine("Server: Whoa, what's up with the extra BOM?");
                        }
                    }
                }
            }
        }

        static async Task Client()
        {
            if (!namedPipeClient.IsConnected)
            {
                namedPipeClient.Connect(6000);
            }

            while (true)
            {
                using (var writer = new StreamWriter(namedPipeClient, System.Text.Encoding.UTF8, 1024, true))
                {
                    Console.ReadKey(true);
                    Console.WriteLine("Client: Received key press, sending request.");
                    string? line = "Hello!";
                    await writer.WriteLineAsync(line);
                    await writer.FlushAsync();
                    Console.WriteLine($"Client: Sent request: {line}");
                }
            }
        }
    }
}

该程序的输出是:

Hello! You are the client. Press any key to send a request.
Client: Received key press, sending request.
Server: Received request: Hello!
Client: Sent request: Hello!
Client: Received key press, sending request.
Server: Received request: ?Hello!
Client: Sent request: Hello!
Server: Whoa, what's up with the extra BOM?
Client: Received key press, sending request.
Server: Received request: ?Hello!
Client: Sent request: Hello!
Server: Whoa, what's up with the extra BOM?

而且这种情况会无休无止地持续下去。因此,该行在发送时不包含额外的 BOM,而是在

StreamReader
读取后才包含。这里发生了什么?

c# .net encoding utf-8 named-pipes
1个回答
0
投票
  1. System.Text.Encoding.UTF8
    提供BOM

它返回一个 UTF8Encoding 对象,该对象提供 Unicode 字节顺序标记 (BOM)。

  1. StreamWriter.FlushAsync
    将 BOM 附加到流中。

  2. StreamWriter.Dispose
    还附加 BOM。

所以如果你还想使用

Encoding.UTF8
,你需要将代码更改为:

using (var writer = new StreamWriter(namedPipeClient, Encoding.UTF8, 1024, true))
{
    while (true)
    {
        Console.ReadKey(true);
        Console.WriteLine("Client: Received key press, sending request.");
        string? line = "Hello!";
        await writer.WriteLineAsync(line);
        //await writer.FlushAsync();
        Console.WriteLine($"Client: Sent request: {line}");
    }
}

当然,你可以构造自定义的UTF8编码对象:

new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.