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) { } } }
可以直接用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) { } } }
接收的方式与服务端类似,对应着改改就行
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(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2021-03-10 数据库简单知识
2021-03-10 MySqlBulkLoader批量上传遇到的问题和解决方法