C# 命名管道通信

先记录一下代码:

 

1. 创建NamedPipeServer类,作为服务端的使用,里面包含创建实例,收发的方法:

复制代码
public class NamedPipeServer
    {
        public NamedPipeServerStream pipeServer;
        //StreamReader sr;
        //StreamWriter sw;

        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="pipename"></param>
        /// <returns></returns>
        public NamedPipeServerStream CreatPipeServer(string pipename)
        {
            pipeServer = new NamedPipeServerStream(pipename, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.None);
            //sr = new StreamReader(pipeServer);
            //sw = new StreamWriter(pipeServer);
            return pipeServer;
        }


        /// <summary>
        /// 接收
        /// </summary>
        /// <returns></returns>
        public string Receive()
        {
            string str="";
            try
            {
                str = pipeServer.ReadByte().ToString();//读取单字节
                
                //str = sr.ReadLine();                 //读取字符串
                //byte[] buffff = new byte[8];
                //pipeServer.Read(buffff, 0, 8);       //读取指定长度的字节数据
                //str = buffff[0].ToString ();

            }
            catch (Exception ex)
            {

            }
            return str;
        }


        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="command"></param>
        public void Send(byte command)
        {
            try
            {
                pipeServer.WriteByte(command);   //发送单字节
                pipeServer.Flush();

                //sw.WriteLine(command);              //发送字符串
                //sw.Flush();

                //byte[] buffff = new byte[2];
                //buffff[0] = command;
                //pipeServer.Write(buffff, 0, 2);   //发送指定长度的字节数据
                Console.WriteLine("Send: " + command);
            }
            catch (Exception ex)
            {

            }
        }

    }
View Code
复制代码

可以直接用NamedPipeServerStream的实例化的类pipeServer进行收发:

(1) 收发单字节:pipeServer.WriteByte();     pipeServer.ReadByte();

(2) 收发字节数组:byte[] buff = new byte[8];

                               buff [0] = 0x01;

                              pipeServer.Write(buff, 0, 8);  //读取指定起点与长度的字节数组       pipeServer.Read(buff, 0, 8);       //读取指定长度的字节数据数组

(3) 收发字符串:这里要用到 StreamWriter 和StreamRead,      sr = new StreamReader(pipeServer);   sw = new StreamWriter(pipeServer);

                            sw.WriteLine();       sr.ReadLine(); 

(4) 收发字符:     sw.Write();              sr.Read();

 

2. 创建NamedPipeClient类,作为客户端的使用,里面包含创建实例,收发的方法:

复制代码
public class NamedPipeClient
    {
        public NamedPipeClientStream pipeClient;
        //StreamReader sr;
        //StreamWriter sw;

        /// <summary>
        /// 创建
        /// </summary>
        /// <param name="pipename"></param>
        /// <returns></returns>
        public NamedPipeClientStream CreatPipeClient(string pipename)
        {
            pipeClient = new NamedPipeClientStream(".", pipename);
            //sr = new StreamReader(pipeClient);
            //sw = new StreamWriter(pipeClient);
            return pipeClient;
        }


        /// <summary>
        /// 接收
        /// </summary>
        /// <returns></returns>
        public string Receive()
        {
            string str = "";
            try
            {
                str = pipeClient.ReadByte().ToString();

                //str = sr.ReadLine();

                //byte[] buffff = new byte[8];
                //pipeClient.Read(buffff, 0, 8);
                //str = buffff[0].ToString();
            }
            catch (Exception ex)
            {

            }
            return str;
        }


        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="command"></param>
        public void Send(byte command)
        {
            try
            {
                pipeClient.WriteByte(command);
                pipeClient.Flush();

                //sw.WriteLine(command);
                //sw.Flush();

                //byte[] buffff = new byte[2];
                //buffff[0] = command;
                //pipeClient.Write(buffff, 0, 2);
            }
            catch (Exception ex)
            {

            }
        }
    }
View Code
复制代码

接收的方式与服务端类似,对应着改改就行 

 

3.总结:

总结几个使用过程中遇到的问题:

(1) 实例化 NamedPipeServerStream 时,PipeTransmissionMode只是数据流传输的方式,发送的是字符串还是字节,由收发字节的方式决定。

(2) 字符串发送时,需要用到Flush();将数据写入基础流,才能把字符串传输出去。

(3) 和C语言或者C++写成的命名管道通讯时,注意限制字符串的长度,否则会收到一大串字符串乱码,掩盖了真正需要收到的字符串。另外C语言需要在字符串的末尾添加"\n".

(4) 命名管道属于半双工通信,接收数据的同时不能发送数据。

(5) Read()或者ReadLine() 会让进程一直卡在这个地方,一直等到另一端发送一个数据过来,可以选择使用asnyc/await避免卡顿问题,

     另外,如果在收到数据之前,想发送一个数据,发送也会卡在Flush();的这个位置,目前,暂未有好的解决办法,希望有大神可以赐教。

 

4. 附上一段操作代码

复制代码
public class OperateProcess
    {
        NamedPipeServer namedPipeServer = new NamedPipeServer();
        Support support = Support.GetInstance();
        ComLog log = new ComLog();

        /// <summary>
        /// 创建流程
        /// </summary>
        /// <returns></returns>
        public bool CreateProcess()
        {
            try
            {
                namedPipeServer.pipeServer = namedPipeServer.CreatPipeServer("testpipe");
                namedPipeServer.pipeServer.WaitForConnection();
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
                return false;
            }

            return true;
        }


        /// <summary>
        /// 结束流程
        /// </summary>
        public bool EndProcess()
        {
            try
            {
                if(!Handshake())
                {
                    return false;
                }

                Thread.Sleep(100);
                SendCommand(0x03);
                if (!ReceiveCommand(30, 0xFE))
                {
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
                return false;
            }


        }



        /// <summary>
        /// 开始流程
        /// </summary>
        public bool StartProcess()
        {
            try
            {
                if (!Handshake())
                {
                    return false;
                }

                Thread.Sleep(100);
                SendCommand(0x01);
                if (!ReceiveCommand(10, 0xFE))
                {
                    return false;
                }
                Thread.Sleep(100);
                if (!ReceiveCommand(10, 0x02))
                {
                    return false;
                }
                SendCommand(0xFF);
                return true;
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
                return false;
            }
            
        }


        /// <summary>
        /// 握手
        /// </summary>
        /// <returns></returns>
        private bool Handshake()
        {
            try
            {
                SendCommand(0x00);
                if (!ReceiveCommand(30, 0xFE))
                {
                    return false;
                }
                SendCommand(0xFF);
                return true;
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
                return false;
            }
        }


        /// <summary>
        /// 发送命令并等待
        /// </summary>
        /// <param name="com"></param>
        public bool SendCommand(byte com, int time)
        {
            namedPipeServer.Send(com);
            log.SendReceiveLog("发送:" + com.ToString(), 0);
            if (!ReceiveCommand(time, 0xFE))
            {
                return false;
            }
            return true;
        }


        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="com"></param>
        public void SendCommand(byte com)
        {
            namedPipeServer.Send(com);
            log.SendReceiveLog("发送:" + com.ToString(), 0);
        }


        /// <summary>
        /// 循环发送
        /// </summary>
        /// <returns></returns>
        public bool CycleSend(byte com, int time)
        {
            int count = 0;
            while (!SendCommand(com,time))
            {
                if (count > 5)
                {
                    return false;
                }
                count++;
            }
            return true;
        }


        /// <summary>
        /// 接收命令
        /// </summary>
        public string ReceiveCommand()
        {
            try
            {
                string str= namedPipeServer.Receive();
                log.SendReceiveLog("接收:" + str, 1);
                if (!string.IsNullOrEmpty(str))
                {
                    return str;
                }
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
            }
            return "";
        }

        /// <summary>
        /// 接收指定的命令
        /// </summary>
        /// <param name="time"></param>
        /// <param name="re"></param>
        /// <returns></returns>
        public bool ReceiveCommand(int time, byte re)
        {
            try
            {
                string str;
                int i = 0;
                while (i < time)
                {
                    str = namedPipeServer.Receive();
                    log.SendReceiveLog("接收:" + str, 1);
                    if (!string.IsNullOrEmpty(str))
                    {
                        if (str == Convert.ToInt32(re).ToString())
                        {
                            return true;
                        }
                    }
                    i++;
                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                support.FunShow(ex);
            }
            return false;
        }


        /// <summary>
        /// 保存日志
        /// </summary>
        public void SaveLog()
        {
            log.SaveLog();
        }
    }
View Code
复制代码

 

posted @   寻找迷途的羔羊  阅读(1077)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
历史上的今天:
2021-03-10 数据库简单知识
2021-03-10 MySqlBulkLoader批量上传遇到的问题和解决方法
点击右上角即可分享
微信分享提示