C#C# 进程通讯-命名管道

    public class Log
    {
        public void L(string msg)
        {
            Console.WriteLine(msg);
        }
        public void L(string format, params string[] data)
        {
            Console.WriteLine(string.Format(format,data));
        }
        public void P(Exception ex, string format, params string[] data)
        {
            var msg = string.Format(format, data);
            Console.WriteLine(string.Format("{0}:{1},{1}", msg, ex.Message, ex.StackTrace));
        }
    }

事先看wcf服务的时候看看wcf有支撑管道通信协议,在此之前不领会,近期正巧有用到这几个,那里写个大致实例

肆能够再扩散的音信上做1些文章,加上ID,发送方和接收方,那样可以完成类似回调的功力,这么些是永葆双向通讯的,那里唯有单向

public class PipServer:Log
    {
        public Action<string> ReceiveEvent;
        NamedPipeServerStream m_pipServer;
        AutoResetEvent monitor = new AutoResetEvent(false);
        Thread m_thread;
        bool run = true;
        string servname;

        public PipServer(string name)
        {
            m_pipServer = new NamedPipeServerStream(name,PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            servname = name;
        }
        public void Listen()
        {
            try
            {
                m_thread = new Thread(() =>
                {
                     WaitConnect();
                });
                m_thread.Start();
            }
            catch (Exception ex)
            {
                P(ex, "[PipServer.WaitForConnect]");
            }
        }
        void WaitConnect()
        {

            AsyncCallback callback = null;
            callback = new AsyncCallback(ar =>
            {
                var pipeServer = (NamedPipeServerStream)ar.AsyncState;
                pipeServer.EndWaitForConnection(ar);
                Accept();
                pipeServer.Disconnect();
                m_pipServer.BeginWaitForConnection(callback, m_pipServer);
            });
            m_pipServer.BeginWaitForConnection(callback, m_pipServer);
        }


        void Accept()
        {
            try
            {

                var res = Read();
                if(!string.IsNullOrEmpty(res))
                    ReceiveEvent?.Invoke(res);
            }
            catch(Exception ex)
            {
                P(ex, "[PipServer.Accept]");
            }
        }
        public bool Send(string msg)
        {
            try
            { 
                var buf = Encoding.UTF8.GetBytes(msg);
                if (m_pipServer.CanWrite)
                {
                    m_pipServer.Write(buf, 0, buf.Length);
                    m_pipServer.Flush();
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                P(ex, "[PipServer.Send]");
                return false;   
            }


        }

        public string Read()
        {
            try
            {
                if (m_pipServer.CanRead)
                {
                    int count = 0;
                    List<byte> data = new List<byte>();
                    byte[] buf = new byte[1024];
                    do
                    {
                        count=m_pipServer.Read(buf, 0, buf.Length);
                        if (count == buf.Length)
                        {
                            data.AddRange(buf);
                        }
                        else
                        {
                            var dst = new byte[count];
                            Buffer.BlockCopy(buf, 0, dst, 0, count);
                            data.AddRange(dst);
                        }                    
                    } while (count > 0&&m_pipServer.CanRead);
                    var res = Encoding.UTF8.GetString(data.ToArray());
                    return res;
                }
                return null;

            }
            catch (Exception ex)
            {
                P(ex, "[PipServer.Read]");
                return null;
            }
        }

        public void Close()
        {
            run = false;
            m_thread.Join();
            if (m_pipServer.IsConnected)
            {
                m_pipServer.Close();
            }

        }
    }

5类库是支撑同步和异步的,那里是异步的等候连接,同步的读取,不过壹般没有平素帮衬4.5await写法的格局,唯有AsyncCallback的写法

 static void  PipTest()
        {
            Thread thread = new Thread(() =>
            {
                PipServer pip = new PipServer("TEST_PIP");
                pip.ReceiveEvent += s =>
                {
                    w(string.Format("receive:{0}",s));
                };
                pip.Listen();
            });
            thread.Start();

            bool send = true;
            int count = 0;
            AutoResetEvent monitor = new AutoResetEvent(false);
            Thread client = new Thread(() =>
            {
                PipClient ct = new PipClient("TEST_PIP");
                while (send)
                {
                    string msg = string.Format("这是第{0}条数据", count);
                    w(msg);
                    ct.Send(msg);
                    count++;
                    if (monitor.WaitOne(1000))
                    {
                        break;
                    }
                }
            });
            client.Start();
            while (true)
            {
                var input = Console.ReadLine();
                if (input == "q" || input == "Q")
                {
                    send = false;
                    monitor.Set();
                    break;
                }
            }
        }

调用实例:

.net有已经封装好的pip通讯的目标NamedPipeServerStream
和NamedPipeClientStream对象,底层应该依然调用C++实现的api实现的

client:

有多少个要留心的点:

  public class PipClient:Log
    {

        string serv;
        public PipClient(string server)
        {
            serv = server;
        }
        public bool Send(string msg)
        {
            try
            {
                var buf = Encoding.UTF8.GetBytes(msg);
                NamedPipeClientStream pipclient = new NamedPipeClientStream(serv);
                pipclient.Connect(3000);
                if (pipclient.CanWrite)
                {
                    pipclient.Write(buf, 0, buf.Length);
                    pipclient.Flush();
                    pipclient.Close();
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                P(ex, "[PipClient.Send]");
                return false;
            }
        }
    }

运营时,是客户端向服务端每隔壹秒发送一回数据

2那里能够用streamreader来读取,然则不用用readend这种写法,假设发送方不如时调用close方法,那样写会直接不通,调用flush也没用

对服务端和客户端做个简单的包裹方便调用:

log类写了贰个不难日志打印类,集成下方便打字与印刷日志,可以平素去掉继承,吧日志打印去掉:

一要留意编码格局,怎么编码就怎么解码,最棒是要有稳定编码,不要直接写string,因为一旦是见仁见智的言语和见仁见智平台完成的类,大概default对应的编码情势是不一致等的,那样会招致读取乱码

3那里初叶化只传入了servername,实际底层的地址是\\\\.\\pipe\\TEST_PIP,调节和测试的时候下个断点能够见见的,借使用C++写的话,间接调用API传入的地址便是真名,到C#那边会活动被分析

server:

 

相关文章