首页 > 解决方案 > 在 C# 中使用命名管道传递消息客户端和服务器

问题描述

我正在尝试创建一个使用命名管道将数据从一个应用程序传递到另一个应用程序的应用程序。在第一次运行时,消息分别由服务器和客户端发送和接收。但是一旦完成,我就无法在服务器和客户端上收到任何消息。

这是我的代码:

服务器端

public void ServerThread(object data)
        {
            var pipeServer =
                new NamedPipeServerStream(_pipelineName, PipeDirection.InOut, numThreads);

            int threadId = Thread.CurrentThread.ManagedThreadId;

            // Wait for a client to connect
            pipeServer.WaitForConnection();

            Console.WriteLine("Client connected on thread[{0}].", threadId);
            try
            {
                // Read the request from the client. Once the client has
                // written to the pipe its security token will be available.
                var ss = new StreamString(pipeServer);

                // Verify our identity to the connected client using a
                // string that the client anticipates.
                ss.WriteString(_securityToken);
                //string filename = ss.ReadString();
                var message = ss.ReadString();

                Console.WriteLine($@"Message received: {message}");
                ss.WriteString("You are connected to the server.");
                Console.WriteLine("Enter message for client.");
                var messageToSend = Console.ReadLine();
                ss.WriteString(messageToSend);
            }
            // Catch the IOException that is raised if the pipe is broken
            // or disconnected.
            catch (IOException e)
            {
                Console.WriteLine("ERROR: {0}", e.Message);
            }
            pipeServer.Close();
        }

客户端

private static string _pipelineName;
        private static string _securityToken;

        public static void Main(string[] args)
        {
            _pipelineName = ConfigurationManager.AppSettings["PipelineName"];
            _securityToken = ConfigurationManager.AppSettings["SecurityToken"];

            var pipeClient =
                new NamedPipeClientStream(".", _pipelineName,
                    PipeDirection.InOut, PipeOptions.None,
                    TokenImpersonationLevel.Impersonation);

            Console.WriteLine($@"Connecting to the server on pipeline {_pipelineName} with password {_securityToken}");
            pipeClient.Connect();

            var ss = new StreamString(pipeClient);
            // Validate the server's signature string.
            if (ss.ReadString() == _securityToken)
            {
                // The client security token is sent with the first write.
                // Send the name of the file whose contents are returned
                // by the server.
                ss.WriteString(@"Client has connected");

                // Print the message to the console.
                Console.Write(ss.ReadString());
            }
            else
            {
                Console.WriteLine("Server could not be verified.");
            }
            pipeClient.Close();
        }

服务器引擎

public class ServerEngine : IServerEngine
    {
        private static int numThreads = 4;
        private readonly string _pipelineName;
        private readonly string _securityToken;


        public ServerEngine(string pipelineName, string securityToken)
        {
            _pipelineName = pipelineName;
            _securityToken = securityToken;

            Console.WriteLine(
                $@"Server is running on {_pipelineName} with password {securityToken}. {'\n'} Waiting for client to connect...");
        }

        public void ServerThread(object data)
        {
            var pipeServer =
                new NamedPipeServerStream(_pipelineName, PipeDirection.InOut, numThreads);

            int threadId = Thread.CurrentThread.ManagedThreadId;

            // Wait for a client to connect
            pipeServer.WaitForConnection();

            Console.WriteLine("Client connected on thread[{0}].", threadId);
            try
            {
                // Read the request from the client. Once the client has
                // written to the pipe its security token will be available.
                var ss = new StreamString(pipeServer);

                // Verify our identity to the connected client using a
                // string that the client anticipates.
                ss.WriteString(_securityToken);
                var message = ss.ReadString();

                Console.WriteLine($@"Message received: {message}");
                ss.WriteString("You are connected to the server.");

                while (true)
                {
                    Console.WriteLine("Enter message for client");
                    var input = Console.ReadLine();
                    if(string.IsNullOrEmpty(input)) break;
                    ss.WriteString(input);
                }
               
            }
            // Catch the IOException that is raised if the pipe is broken
            // or disconnected.
            catch (IOException e)
            {
                Console.WriteLine("ERROR: {0}", e.Message);
            }
            pipeServer.Close();
        }

        private void asdfasf()
        {

        }
    }

串流

public class StreamString : IStreamString
    {
        private readonly Stream _ioStream;
        private readonly UnicodeEncoding _streamEncoding;

        public StreamString(Stream ioStream)
        {
            _ioStream = ioStream;
            _streamEncoding = new UnicodeEncoding();
        }

        public string ReadString()
        {
            var len = _ioStream.ReadByte() * 256;
            len += _ioStream.ReadByte();
            byte[] inBuffer = new byte[len];
            _ioStream.Read(inBuffer, 0, len);

            return _streamEncoding.GetString(inBuffer);
        }

        public int WriteString(string outString)
        {
            byte[] outBuffer = _streamEncoding.GetBytes(outString);
            int len = outBuffer.Length;
            if (len > UInt16.MaxValue)
            {
                len = ushort.MaxValue;
            }
            _ioStream.WriteByte((byte)(len / 256));
            _ioStream.WriteByte((byte)(len & 255));
            _ioStream.Write(outBuffer, 0, len);
            _ioStream.Flush();

            return outBuffer.Length + 2;
        }
    }

标签: c#named-pipes

解决方案


推荐阅读