命名管道的C#实现
1. 命名管道简介
"命名管道"或"命名管线"(Named Pipes)是一种简单的进程间通信(I P C)机制,Microsoft Windows NT,Windows 2000,Windows 95以及Windows 98均提供了对它的支持(但不包括Windows CE).命名管道可在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间,支持可靠的,单向或双向的数据通信.用命名管道来设计应用程序实际非常简单,并不需要事先深入掌握基层网络传送协议(如T C P / I P或I P X)的知识.这是由于命名管道利用了微软网络提供者(M S N P)重定向器,通过一个网络,在各进程间建立通信.这样一来,应用程序便不必关心网络协议的细节.之所以要用命名管道作为自己的网络通信方案,一项重要的原因是它们充分利用了Windows NT及Windows 2000内建的安全特性.
2.命名管道作用
这里有一个可采纳命令管道的例子.假定我们要开发一个数据管理系统,只允许一个指定的用户组进行操作.想像在自己的办公室中,有一部计算机,其中保存着公司的秘密.我们要求只有公司的管理人员,才能访问及处理这些秘密.假定在自己的工作站机器上,公司内的每名员工都可看到网络上的这台计算机.然而,我们并不希望普通员工取得对机密材料的访问权.在这种情况下,命名管道可发挥出很好的作用,因为我们可开发一个服务器应用程序,令其以来自客户机的请求为准,对公司的秘密进行安全操作.服务器可将客户访问限制在管理人员身上,用Windows NT或新版Windows 2000自带的安全机制,便可非常轻松地做到这一点.在此要记住的一个重点是,将命名管道作为一种网络编程方案使用时,它实际上建立一个简单的客户机/服务器数据通信体系,可在其中可靠地传输数据.
3. 命名管道优点
使用比较方便,并且不需要声明端口号之类的,在程序中不需要关心权限之类的。
4. 命名管道限制(我个人认为)
管道只能一对一链接通信。
5. 命名管道实现
5.1 命名管道通讯辅助类
/// <summary> /// pipe命名管道通讯辅助类 /// </summary> public class StreamString { private Stream ioStream; private UnicodeEncoding streamEncoding; public StreamString(Stream ioStream) { this.ioStream = ioStream; streamEncoding = new UnicodeEncoding(); } public string ReadString() { try { int len; len = ioStream.ReadByte() * 256; len += ioStream.ReadByte(); byte[] inBuffer = new byte[len]; ioStream.Read(inBuffer, 0, len); return streamEncoding.GetString(inBuffer); } catch (Exception) { return null; } } public int WriteString(string outString) { byte[] outBuffer = streamEncoding.GetBytes(outString); int len = outBuffer.Length; if (len > UInt16.MaxValue) { len = (int)UInt16.MaxValue; } ioStream.WriteByte((byte)(len / 256)); ioStream.WriteByte((byte)(len & 255)); ioStream.Write(outBuffer, 0, len); ioStream.Flush(); return outBuffer.Length + 2; } } /// <summary> /// 自定义包装类 /// </summary> public class StringToStream { private string Contents; private StreamString streamString; public StringToStream(StreamString ss, string contents) { Contents = contents; streamString = ss; } public void Start() { //string contents = File.ReadAllText(fn); streamString.WriteString(Contents); } }
5.2 命名管道服务器端帮助类
public class PipeHelp { private static int numThreads = 1; /// <summary> /// 启动管道服通讯务器 /// </summary> public static void PipeSeverSart() { try { int i; Thread[] servers = new Thread[numThreads]; Console.WriteLine("Waiting for client connect...\n"); for (i = 0; i < numThreads; i++) { servers[i] = new Thread(ServerThread); servers[i].Start(); } } catch (Exception) { throw new Exception("管道服务启动失败."); //PipeSeverSart(); } } /// <summary> /// 退出管道。(程序退出时别忘了调用) /// </summary> public static void PipeSeverClose() { if (pipeServer != null) { try { pipeServer.Disconnect(); pipeServer.Close(); } catch (Exception exception) { Console.WriteLine(exception.Message); } } } private static NamedPipeServerStream pipeServer; /// <summary> /// 处理函数 /// </summary> /// <param name="data"></param> private static void ServerThread(object data) { try { Random reRandom = new Random(); pipeServer = new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads); //int threadId = Thread.CurrentThread.ManagedThreadId; // Wait for a client to connect pipeServer.WaitForConnection(); StreamString ss = new StreamString(pipeServer); //Console.WriteLine("Client connected on thread[{0}].", threadId); while (true) { try { // Read the request from the client. Once the client has // written to the pipe its security token will be available. //ss.WriteString("I am the one true server!"); string temp = ss.ReadString(); if (temp != null) { if (temp.ToLower() == "close")//客户端通知服务器客户端退出 { //为了客户端退出之后,可以再次连接到服务器端,重新设置一下服务i其管道 Close(); pipeServer = new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads); pipeServer.WaitForConnection(); ss = new StreamString(pipeServer); } else { StringToStream fileReader = new StringToStream(ss, SystemHelp.BusinessSystemID); pipeServer.RunAsClient(fileReader.Start); } } else////客户端未通知服务器客户端退出,客户端直接异常退出 { Close(); pipeServer = new NamedPipeServerStream("VisualPlatformPipe", PipeDirection.InOut, numThreads); pipeServer.WaitForConnection(); ss = new StreamString(pipeServer); } } // Catch the IOException that is raised if the pipe is broken // or disconnected. catch (IOException e) { Console.WriteLine("ERROR: {0}", e.Message); } } } catch (Exception) { throw new Exception("管道服务启动失败."); } } /// <summary> /// 退出管道 /// </summary> public static void Close() { if (pipeServer != null) { pipeServer.Disconnect(); pipeServer.Close(); } } }
5.3客户端帮助类
public class PipeClientHelp { private static StreamString m_StreamString = null; private static NamedPipeClientStream pipeClient = null; /// <summary> /// 启动客户端,连接服务器,只允许连接一次 /// </summary> /// <returns></returns> public static bool StartConnection() { try { if (pipeClient == null) { pipeClient = new NamedPipeClientStream(".", "VisualPlatformPipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation); pipeClient.Connect(100); m_StreamString = new StreamString(pipeClient); } } catch (Exception exception) { pipeClient = null; throw new Exception("未启动服务器端" + exception.Message); } return true; } /// <summary> /// 通知服务器客户端即将退出 /// </summary> public static void ClosePipe() { if (pipeClient != null) { m_StreamString.WriteString("close"); m_StreamString = null; pipeClient.Close(); pipeClient = null; } } /// <summary> /// 从服务器获取数据 /// </summary> /// <returns></returns> public static string GetSystemID() { if (m_StreamString != null) { m_StreamString.WriteString("GetBusinessSystemId"); return m_StreamString.ReadString(); } return null; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构