C# 命名管道 - 编码错误?

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

我是第一次使用命名管道。我的最终目标是制作一个既可以作为客户端、服务器又可以独立工作的 exe。服务器可以具有提升的权限。

我在来回连接时遇到困难。首先,除了第一个之外,每次写回客户端的操作都以“?”开头。互联网说它是一个编码问题,但它是执行此操作的相同函数(writeClient),因此我无法确定为什么第一次会有所不同。 (打印输出也确认了作者和读者每次都说相同的编码)第二是我想确保我正确地关闭了连接。这需要一些尝试和错误。

从客户端读出
在此版本中,我告诉它也打印编码以确认它没有更改。

已连接。
安装的版本:1.2.8
?最新版本:1.2.85
?需要更新
?再次运行而不使用“-Check”以执行静默安装。
?关闭
连接已关闭。

主程序

using System;
using System.Diagnostics;
using System.Xml.Linq;
using System.Runtime.Versioning;
using System.IO.Pipes;
using System.Text;
using System.Net;
using System.ServiceProcess;
using System.Security.Authentication.ExtendedProtection;

[SupportedOSPlatform("windows")]

class DAQUpdate
{
    static void Main(string[] args)
    {       
        if (args.Length > 0)
        {

                //Check if the same program is running as a service. If so, use that as it will have elevated previleges 
                try
                {
                    using (NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "DAQUpdater", PipeDirection.InOut))
                    {
                        //Connect to the service with a 1 second timeout. This will return an error on timeout
                        pipeClient.Connect(1);
                        //Double check if connected for reasons.
                        if(pipeClient.IsConnected)
                        {
                            Console.WriteLine("Connected.");

                            // Send the args to the server
                            using (StreamWriter writer = new StreamWriter(pipeClient,Encoding.UTF8,-1,true))
                            {
                                //Packages the args with ; to separate since I can't pass objects
                                writer.WriteLine(string.Join(';', args));
                                writer.Flush();
                            }

                            //Read all responses from the server as it gives them. The final response will be Close
                            string response = "";                               
                            using (StreamReader reader = new StreamReader(pipeClient, Encoding.UTF8))
                            {
                                while(!response.Contains("Close"))
                                {                                    
                                    response = reader.ReadLine();
                                    Console.WriteLine(response);
                                }
                                pipeClient.Close();
                            }
                            Console.WriteLine("Connection closed.");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine("No Connection.");
                }            
        }
        else
        {
            NamedPipeServer.runServer();
        }
    }
    public static void update(string[] args)
    {
        NamedPipeServer.writeClient("hello");
        NamedPipeServer.writeClient(args[0]);
        NamedPipeServer.writeClient("Testing");
        NamedPipeServer.writeClient("Close");
    }
    
}

服务器功能

// NamedPipeServer.cs

using System.IO.Pipes;
using System.Text;

public class NamedPipeServer
{
    private static NamedPipeServerStream pipeServer;
    public static void runServer()
    {
        try
        {            
            while(true)
            {
                //Changed to global so other functions can call writeClient and send messages to the client from anywhere
                pipeServer = new NamedPipeServerStream("DAQUpdater", PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

                {
                    Console.WriteLine("Waiting for connection...");
                    pipeServer.WaitForConnection();
                    Console.WriteLine("Client connected.");

                    // Read and process the command from the client
                    using (StreamReader reader = new StreamReader(pipeServer, Encoding.UTF8,true,-1,true ))
                    {
                        string command = reader.ReadLine();
                        string[] commandargs = command.Split(';');
                        Console.WriteLine($"Received command: {commandargs[0]}");

                        //Run the check for updates program which will also write to the client
                        DAQUpdate.update(commandargs);

                        // Send a response back to the client if needed
                        using (StreamWriter writer = new StreamWriter(pipeServer, Encoding.UTF8, -1 , true))
                        {
                            writer.WriteLine("Close");
                            writer.Flush();
                        }
                    }
                    pipeServer.Close();
                    Console.WriteLine("Connection closed.");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
    public static void writeClient(string messageTxt)
    {
        //allows other functions to send update messages to the client
        if(pipeServer != null)
        {
            if(pipeServer.IsConnected)
            {
                using (StreamWriter writer = new StreamWriter(pipeServer, Encoding.UTF8, -1 , true))
                {
                    Console.WriteLine(writer.Encoding);
                    writer.WriteLine(messageTxt);
                    writer.Flush();
                }
            }
        }                
    }
}


c# named-pipes
1个回答
0
投票

您正在为每一行创建一个单独的

StreamWriter
,这将从发出您指定的
Encoding
的前导码开始 -
Encoding.UTF8
包括字节顺序标记的前导码。

怀疑你没有在第一行看到它,因为

StreamReader
很可能会默默地从输入的开头剥离它。 (说实话,我不太记得作者/读者何时发出/删除它的细节。)

我建议您在

Utf8EncodingWithoutPreamble
的某处创建一个简单的静态属性,通过
new Utf8Encoding(false)
初始化。如果你每次写作时都使用它,你将不会得到序言。

或者,您可以创建一个

StreamWriter
并保持打开状态,这样它只会写入将被剥离的一个序言。

或者,您可以完全放弃

StreamWriter
,只使用:

pipeServer.Write(Encoding.Utf8.GetBytes(messageTxt + "\n"));

(除了其他任何事情之外,我建议使用明确定义的换行符,而不是默认的“无论平台默认换行符是什么。)

© www.soinside.com 2019 - 2024. All rights reserved.