使用命名管道实现进程间通信

简介:

创建命名管道

命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的。相比TCP通信方式,效率更高,但比共享内存要低点。
命名管道可以在本地机器或者局域网内机器实现进程间通信,所以是最佳的通信方式。

创建一个NamedPipeServerStream:

NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipName, PipeDirection.InOut, 10);

这里表示命名管道服务器的管道放心为双向通信,类似于TCP双工。接着,使用下面的代码等待连接:

pipeServer.WaitForConnection();

如果有连接,就可以使用流阅读器进行阅读:

 StreamReader sr = new StreamReader(pipeServer);

同样,也可以使用流写操作器,将数据写入流,管道的另一端,可以读取这个流:

复制代码
 using (StreamWriter sw = new StreamWriter(pipeServer))
 {
       sw.AutoFlush = true;
       sw.WriteLine("hello world " + str);
 }
复制代码

注意:此处使用了using,意味着写完就会关闭流,但同时也会关闭管道,所以需要注意。假如客户端要读取全部数据,那么需要等到这里关闭流。

自定义应用层通信协议

如何读取管道的全部数据,看下面的代码:

 StreamReader sr = new StreamReader(pipeServer);
 string text =sr.ReadToEnd();

这种方式可以读取全部数据,但是,在管道的另外一段,如果留写操作器不调用 Close方法,这里没法读取完成,程序会阻塞在这里。 所以,必须定义一个“应用协议”,客户端告诉服务端合适结束读取数据。

我们仿照HTTP协议的方法,使用连续的2个以上的回车换行表示HTTP头信息结束,我们也这样定义,并附加其它标记来表示流数据发送完毕,参考发送端:

复制代码
 public string Query(string request)
        {
            if (!_pipeClient.IsConnected)
            {
                _pipeClient.Connect(10000);
            }

            StreamWriter sw = new StreamWriter(_pipeClient);
            sw.WriteLine(request);
            sw.WriteLine();//连续2个换行外加"#END"表示结束
            sw.WriteLine();
            sw.WriteLine("#END");
            sw.Flush();

            StreamReader sr = new StreamReader(_pipeClient);
            string returnVal = sr.ReadToEnd();
            return returnVal;
        }
复制代码

而在服务端,采用下面的方式完成流数据的读取:

复制代码
string str = null;
 string strAll = null;
 System.Text.StringBuilder sb = new System.Text.StringBuilder();

 StreamReader sr = new StreamReader(pipeServer);
 while (pipeServer.CanRead && (null != (str = sr.ReadLine())))
 {
     
     //当遇到连续2个换行外加#END,表示输入结束
     if (str == "#END" )
     {
         strAll = sb.ToString();
         if (strAll.EndsWith("\r\n\r\n"))
             break;
     }
     else
     {
         if (str == "")
             sb.AppendLine();
         else
             sb.AppendLine(str);
     }
 }

 strAll = strAll.Substring(0, strAll.Length - "\r\n\r\n\r\n".Length);
复制代码

测试和下载

最后,写个客户端和服务端控制台程序:

复制代码
namespace NamePipedSample_Server
{
    class Program
    {
        static void Main(string[] args)
        {
            NamedPipeListenServer svr = new NamedPipeListenServer("test");
            svr.Run();
            Console.Read();
        }
    }
}
复制代码
复制代码
namespace NamePipedSample_Client
{
    class Program
    {
        static void Main(string[] args)
        {
            string sendStr = null;
            using (NamedPipeClient client = new NamedPipeClient(".", "test"))
            {
                sendStr = "fff\r\ndddd\r\n";
                Console.WriteLine("send:{0}",sendStr);
                Console.WriteLine("Reply:{0}",client.Query(sendStr));

                sendStr = "54353";
                Console.WriteLine("send:{0}", sendStr);
                Console.WriteLine("Reply:{0}", client.Query(sendStr));

                sendStr = "aaaaaaa";
                Console.WriteLine("send:{0}", sendStr);
                Console.WriteLine("Reply:{0}", client.Query(sendStr));
            }
            Console.WriteLine("send all ok.");
            Console.Read();
        }
    }
}
复制代码

 跨机器使用命名管道


上面的程序在本地机器使用没问题的,但是跨机器可能会遇到问题,在使用的时候,需要将主机名字 "." 替换成
实际的局域网主机名字,例如:

using (NamedPipeClient client = new NamedPipeClient("user-xxxPc", "test"))
{
 //
}

但是这样可能还是无法访问,会报下面的错误:

“System.IO.IOException”类型的未经处理的异常在 System.Core.dll 中发生 

其他信息: 登录失败: 未知的用户名或错误密码。

此时需要在客户机器上,地址栏里面输入下面的地址: \\user-xxxPc

此时会提示输入用户名,密码,最后勾选 “记住账号”,下次即可使用了。

 

经过测试,这种方法是先命名管道客户端-服务器通信成功。 本文程序是在网友原来文章的基础上改进的,在此表示感谢,原文地址:  http://blog.csdn.net/educast/article/details/7219774

本文程序Demo下载



    本文转自深蓝医生博客园博客,原文链接:http://www.cnblogs.com/bluedoctor/p/4671086.html,如需转载请自行联系原作者



相关文章
|
23天前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
3月前
|
消息中间件 Unix Linux
C语言 多进程编程(二)管道
本文详细介绍了Linux下的进程间通信(IPC),重点讨论了管道通信机制。首先,文章概述了进程间通信的基本概念及重要性,并列举了几种常见的IPC方式。接着深入探讨了管道通信,包括无名管道(匿名管道)和有名管道(命名管道)。无名管道主要用于父子进程间的单向通信,有名管道则可用于任意进程间的通信。文中提供了丰富的示例代码,展示了如何使用`pipe()`和`mkfifo()`函数创建管道,并通过实例演示了如何利用管道进行进程间的消息传递。此外,还分析了管道的特点、优缺点以及如何通过`errno`判断管道是否存在,帮助读者更好地理解和应用管道通信技术。
|
3月前
|
SQL 网络协议 数据库连接
已解决:连接SqlServer出现 provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程【C#连接SqlServer踩坑记录】
本文介绍了解决连接SqlServer时出现“provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程”错误的步骤,包括更改服务器验证模式、修改sa用户设置、启用TCP/IP协议,以及检查数据库连接语句中的实例名是否正确。此外,还解释了实例名mssqlserver和sqlserver之间的区别,包括它们在默认设置、功能和用途上的差异。
|
4月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
175 3
|
4月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
72 0
|
4月前
|
Linux C语言
【C语言】进程间通信之命名管道fifo
【C语言】进程间通信之命名管道fifo
46 0
|
4月前
|
C语言
【C语言】进程间通信之管道pipe
【C语言】进程间通信之管道pipe
92 0
|
4月前
|
Python
Python IPC深度探索:解锁跨进程通信的无限可能,以管道与队列为翼,让你的应用跨越边界,无缝协作,震撼登场
【8月更文挑战第3天】Python IPC大揭秘:解锁进程间通信新姿势,让你的应用无界连接
27 0
|
4月前
|
消息中间件 存储 网络协议
从零开始掌握进程间通信:管道、信号、消息队列、共享内存大揭秘
在操作系统中,进程间通信(IPC)是至关重要的,它提供了多种机制来实现不同进程间的数据交换和同步。本篇文章将详细介绍几种常见的IPC方式,包括管道、信号、消息队列、共享内存、信号量和套接字,帮助你深入理解并合理应用这些通信方式,提高系统性能与可靠性。
379 0
|
5月前
|
Unix Linux Python
`subprocess`模块是Python中用于生成新进程、连接到它们的输入/输出/错误管道,并获取它们的返回(退出)代码的模块。
`subprocess`模块是Python中用于生成新进程、连接到它们的输入/输出/错误管道,并获取它们的返回(退出)代码的模块。