使用命名管道实现进程间通信
创建命名管道
命名管道常常用于应用程序之间的通迅,由于不需要进行序列化和反序列化操作,效率是非常高的。相比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("rnrn"))
break;
}
else
{
if (str == "")
sb.AppendLine();
else
sb.AppendLine(str);
}
}
strAll = strAll.Substring(0, strAll.Length - "rnrnrn".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 = "fffrnddddrn";
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下载
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP设计模式之单例模式定义与用法分析
- PHP面向对象程序设计之接口的继承定义与用法详解
- PHP简单验证码功能机制实例详解
- php高清晰度无损图片压缩功能的实现代码
- Python自省及反射原理实例详解
- 浅谈django框架集成swagger以及自定义参数问题
- keras CNN卷积核可视化,热度图教程
- 解决tensorflow读取本地MNITS_data失败的原因
- 浅谈keras中Dropout在预测过程中是否仍要起作用
- 浅谈keras中loss与val_loss的关系
- python中tkinter窗口位置坐标大小等实现示例
- python os模块在系统管理中的应用
- Laravel路由研究之domain解决多域名问题的方法示例
- python GUI模拟实现计算器
- 详解php命令注入攻击