微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过NamedPipe命名管道实现进程间通信C#实现,包括客户端和服务端

一、前言

最近在做一个这样的功能Unity发布PC平台的客户端exe,在客户端exe中拉起浏览器exe(这个浏览器是自己使用winform实现的),浏览器内调用JsApi执行支付,支付结果会回调游戏服务端URL,服务端通过消息通知客户端exe,此时客户端exe通过进程间通信让浏览器exe关闭

好了,进程间怎么通信呢?
实现进程间通信有很多中方案:管道(pipe)、命名管道(FIFO)、消息队列(MessageQueue)、共享存储(SharedMemory)、信号量(Semaphore)、套接字(Socket)、信号 ( sinal)等。

本文要实现的是命名管道的方案。

在这里插入图片描述

二、关于命名管道

命名管道又名命名管线Named Pipes),是一种简单的进程间通信(IPC)机制,Microsoft Windows大都提供了对它的支持(但不包括Windows CE)。命名管道可在同一台计算机的不同进程之间或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。
命名管道的所有实例拥有相同的名称,但是每个实例都有其自己的缓冲区和句柄。
windows中命名管道的通信方式是:1、创建命名管道;2、连接命名管道;3读写命名管道。

三、运行效果

在这里插入图片描述

四、Demo工程源码

Demo工程源码我已上传CODE CHINA,感兴趣的同学可以下载下来学习。
地址:https://codechina.csdn.net/linxinfa/csharp-namedpipe-demo

在这里插入图片描述

五、核心代码

具体代码详见上面的Demo工程。

服务端

/// <summary>
/// 服务端管道
/// </summary>
class NamedPipeServer
{
    private NamedPipeServerStream Server { get; set; }
    private byte[] Buffer;
    private int BufferSize = 10;
    private StringBuilder InputStr { get; set; }

    public NamedPipeServer(string name)
    {
        this.Server = new NamedPipeServerStream(name,
            PipeDirection.InOut,
            1,
            PipeTransmissionMode.Message,
            PipeOptions.None);
        this.InputStr = new StringBuilder();
        Buffer = new byte[BufferSize];
    }

    public void Start()
    {
        while (true)
        {
            this.Server.WaitForConnection();

            AsyncState asyncState = new AsyncState()
            {
                Buffer = new byte[BufferSize],
                EvtHandle = new ManualResetEvent(false),
                Stream = this.Server
            };

            //异步读取,并阻塞线程,读取结束取消阻塞
            this.Server.BeginRead(this.Buffer, 0, this.Buffer.Length, new AsyncCallback(ReadCallback), asyncState);
            asyncState.EvtHandle.WaitOne();

            //获取输出字符串
            string outStr = "";
            if (Readed != null) outStr = this.Readed.Invoke(this.InputStr.ToString().Replace("\0", " ").Trim()).Trim();
            this.InputStr.Clear();
            for (int i = 0; i < this.BufferSize; i++)
                outStr = " " + outStr;

            //输出到内存流,然后内存流转写字节码到服务流中
            using (MemoryStream memoryStream = new MemoryStream())
            using (StreamWriter write = new StreamWriter(memoryStream))
            {
                write.Write(outStr);
                write.Flush();
                memoryStream.Flush();
                int length = 0;
                memoryStream.Position = 0;
                byte[] tmp = new byte[BufferSize];
                while (((length = memoryStream.Read(tmp, this.Buffer.Length)) != 0))
                {
                    Server.Write(tmp, length);
                }
            }

            Server.WaitForPipeDrain();
            Server.Flush();
            Server.disconnect();
        }
    }


    private void ReadCallback(IAsyncResult arg)
    {
        AsyncState state = arg.AsyncState as AsyncState;
        int length = state.Stream.EndRead(arg);

        if (length > 0)
        {
            byte[] buffer;
            if (length == BufferSize) buffer = state.Buffer;
            else
            {
                buffer = new byte[length];
                Array.copy(state.Buffer, buffer, length);
            }

            if (state.MemoryStream == null) state.MemoryStream = new MemoryStream();
            state.MemoryStream.Write(buffer, buffer.Length);
            state.MemoryStream.Flush();
        }
        if (length < BufferSize)
        {
            state.MemoryStream.Position = 0;
            using (StreamReader reader = new StreamReader(state.MemoryStream))
            {
                this.InputStr.Append(reader.ReadToEnd());
            }
            state.MemoryStream.Close();
            state.MemoryStream.dispose();
            state.MemoryStream = null;

            state.EvtHandle.Set();
        }
        else
        {
            Array.Clear(state.Buffer, BufferSize);
            //再次执行异步读取操作
            state.Stream.BeginRead(state.Buffer, BufferSize, state);
        }
    }
    public event Func<string, string> Readed;
}

客户端

/// <summary>
/// 客户端管道
/// </summary>
class NamedPipeClient
{
    private NamedPipeClientStream Client { get; set; }
    private byte[] Buffer { get; set; }
    private bool IsReadEnd { get; set; }
    private bool IsWriteEnd { get; set; }
    private int BufferSize = 10;
    private StringBuilder InputStr { get; set; }
    private string OutputStr { get; set; }

    public NamedPipeClient(string serverName, string serverHost)
    {
        Client = new NamedPipeClientStream(serverHost, serverName);
        this.Buffer = new byte[BufferSize];
        this.InputStr = new StringBuilder();
    }

    public string Request(string outPutStr)
    {
        this.OutputStr = outPutStr.Trim();
        this.Client.Connect();

        for (int i = 0; i < this.BufferSize; i++)
            this.OutputStr = " " + this.OutputStr;
        using (MemoryStream memoryStream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(memoryStream))
        {

            writer.Write(OutputStr);
            writer.Flush();
            memoryStream.Flush();
            int length = 0;
            memoryStream.Position = 0;
            while ((length = memoryStream.Read(Buffer, Buffer.Length)) != 0)
            {
                this.Client.Write(Buffer, length);
            }
            this.Client.WaitForPipeDrain();
            this.Client.Flush();
        }

        AsyncState asyncState = new AsyncState()
        {
            Buffer = new byte[BufferSize],
            EvtHandle = new ManualResetEvent(false),
            Stream = this.Client
        };

        IAsyncResult readAsyncResult = this.Client.BeginRead(this.Buffer, asyncState);
        asyncState.EvtHandle.WaitOne();

        this.Client.Close();
        this.Client.dispose();

        return this.InputStr.ToString().Replace("\0", " ").Trim();
    }

    private void ReadCallback(IAsyncResult arg)
    {
        AsyncState state = arg.AsyncState as AsyncState;
        int length = state.Stream.EndRead(arg);

        if (length > 0)
        {
            byte[] buffer;
            if (length == BufferSize) buffer = state.Buffer;
            else
            {
                buffer = new byte[length];
                Array.copy(state.Buffer, state);
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐