之前看wcf服务的时候看到wcf有支持管道通信协议,之前不知道,最近刚好有用到这个,这里写个简单实例

.net有已经封装好的pip通信的对象NamedPipeServerStream 和NamedPipeClientStream对象,底层应该还是调用C++实现的api实现的

对服务端和客户端做个简单的封装方便调用:

server:

public class PipServer:Log
{
public Action<string> ReceiveEvent;
NamedPipeServerStream m_pipServer;
AutoResetEvent monitor = new AutoResetEvent(false);
Thread m_thread;
bool run = true;
string servname; public PipServer(string name)
{
m_pipServer = new NamedPipeServerStream(name,PipeDirection.InOut, , PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
servname = name;
}
public void Listen()
{
try
{
m_thread = new Thread(() =>
{
WaitConnect();
});
m_thread.Start();
}
catch (Exception ex)
{
P(ex, "[PipServer.WaitForConnect]");
}
}
void WaitConnect()
{ AsyncCallback callback = null;
callback = new AsyncCallback(ar =>
{
var pipeServer = (NamedPipeServerStream)ar.AsyncState;
pipeServer.EndWaitForConnection(ar);
Accept();
pipeServer.Disconnect();
m_pipServer.BeginWaitForConnection(callback, m_pipServer);
});
m_pipServer.BeginWaitForConnection(callback, m_pipServer);
} void Accept()
{
try
{ var res = Read();
if(!string.IsNullOrEmpty(res))
ReceiveEvent?.Invoke(res);
}
catch(Exception ex)
{
P(ex, "[PipServer.Accept]");
}
}
public bool Send(string msg)
{
try
{
var buf = Encoding.UTF8.GetBytes(msg);
if (m_pipServer.CanWrite)
{
m_pipServer.Write(buf, , buf.Length);
m_pipServer.Flush();
return true;
}
return false;
}
catch (Exception ex)
{
P(ex, "[PipServer.Send]");
return false;
} } public string Read()
{
try
{
if (m_pipServer.CanRead)
{
int count = ;
List<byte> data = new List<byte>();
byte[] buf = new byte[];
do
{
count=m_pipServer.Read(buf, , buf.Length);
if (count == buf.Length)
{
data.AddRange(buf);
}
else
{
var dst = new byte[count];
Buffer.BlockCopy(buf, , dst, , count);
data.AddRange(dst);
}
} while (count > &&m_pipServer.CanRead);
var res = Encoding.UTF8.GetString(data.ToArray());
return res;
}
return null; }
catch (Exception ex)
{
P(ex, "[PipServer.Read]");
return null;
}
} public void Close()
{
run = false;
m_thread.Join();
if (m_pipServer.IsConnected)
{
m_pipServer.Close();
} }
}

client:

  public class PipClient:Log
{ string serv;
public PipClient(string server)
{
serv = server;
}
public bool Send(string msg)
{
try
{
var buf = Encoding.UTF8.GetBytes(msg);
NamedPipeClientStream pipclient = new NamedPipeClientStream(serv);
pipclient.Connect();
if (pipclient.CanWrite)
{
pipclient.Write(buf, , buf.Length);
pipclient.Flush();
pipclient.Close();
return true;
}
return false;
}
catch (Exception ex)
{
P(ex, "[PipClient.Send]");
return false;
}
}
}

log类写了一个简单日志打印类,集成下方便打印日志,可以直接去掉继承,吧日志打印去掉:

    public class Log
{
public void L(string msg)
{
Console.WriteLine(msg);
}
public void L(string format, params string[] data)
{
Console.WriteLine(string.Format(format,data));
}
public void P(Exception ex, string format, params string[] data)
{
var msg = string.Format(format, data);
Console.WriteLine(string.Format("{0}:{1},{1}", msg, ex.Message, ex.StackTrace));
}
}

调用实例:

 static void  PipTest()
{
Thread thread = new Thread(() =>
{
PipServer pip = new PipServer("TEST_PIP");
pip.ReceiveEvent += s =>
{
w(string.Format("receive:{0}",s));
};
pip.Listen();
});
thread.Start(); bool send = true;
int count = ;
AutoResetEvent monitor = new AutoResetEvent(false);
Thread client = new Thread(() =>
{
PipClient ct = new PipClient("TEST_PIP");
while (send)
{
string msg = string.Format("这是第{0}条数据", count);
w(msg);
ct.Send(msg);
count++;
if (monitor.WaitOne())
{
break;
}
}
});
client.Start();
while (true)
{
var input = Console.ReadLine();
if (input == "q" || input == "Q")
{
send = false;
monitor.Set();
break;
}
}
}

运行时,是客户端向服务端每隔一秒发送一次数据

有几个要注意的点:

1 要注意编码方式,怎么编码就怎么解码,最好是要有固定编码,不要直接写string,因为如果是不同的语言和不同平台实现的类,可能default对应的编码方式是不一样的,这样会造成读取乱码

2 这里可以用streamreader来读取,但是不要用readend这种写法,如果发送方不及时调用close方法,这样写会一直卡住,调用flush也没用

3 这里初始化只传入了servername,实际底层的地址是\\\\.\\pipe\\TEST_PIP,调试的时候下个断点可以看到的,如果用C++写的话,直接调用API传入的地址就是全名,到C#这边会自动被解析

4 可以再传入的信息上做一些文章,加上ID,发送方和接收方,这样可以实现类似回调的功能,这个是支持双向通信的,这里只有单向

5 类库是支持同步和异步的,这里是异步的等待连接,同步的读取,但是貌似没有直接支持4.5await写法的方法,只有AsyncCallback的写法

C# 进程通信-命名管道的更多相关文章

  1. Linux学习笔记(13)-进程通信|命名管道

    匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...

  2. 进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道

    管道 Linux环境进程间通信(一) https://www.ibm.com/developerworks/cn/linux/l-ipc/part1/index.html 管道及有名管道 郑彦兴200 ...

  3. Linux下进程通信之管道

    每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把 ...

  4. c# c++通信--命名管道通信

    进程间通信有很多种,windows上面比较简单的有管道通信(匿名管道及命名管道) 最近做个本机c#界面与c++服务进行通信的一个需求.简单用命名管道通信.msdn都直接有demo,详见下方参考. c+ ...

  5. linux下的进程通信之管道与FIFO

    概念:管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条.管道的一端连接一个进程的输出.这个进程会向管道中放入信息.管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息. 优点:不需 ...

  6. Linux进程通信----匿名管道

    Linux进程通信中最为简单的方式是匿名管道 匿名管道的创建需要用到pipe函数,pipe函数参数为一个数组表示的文件描述字.这个数组有两个文件描 述字,第一个是用于读数据的文件描述符第二个是用于写数 ...

  7. linux进程通信之管道

    1.介绍: 1)同一主机: unix进程通信方式:无名管道,有名管道,信号 system v方式:信号量,消息队列,共享内存 2)网络通信:Socket,RPC 2.管道: 无名管道(PIPE):使用 ...

  8. 进程通信类型 管道是Linux支持的最初Unix IPC形式之一

    管道 Linux环境进程间通信(一) https://www.ibm.com/developerworks/cn/linux/l-ipc/part1/index.html 管道及有名管道 郑彦兴200 ...

  9. linux 进程通信之 管道和FIFO

    进程间通信:IPC概念 IPC:Interprocess Communication,通过内核提供的缓冲区进行数据交换的机制. IPC通信的方式: pipe:管道(最简单) fifo:有名管道 mma ...

随机推荐

  1. 修改linux的文件时,如何快速找到要修改的内容

    ♦ 在linux系统下,找到需要修改的文件.使用cd+目录的命令进行文件所在的目录,使用ls命令查看是否有该文件. ♦ 使用vim+文件名,打开该文件 ♦ 快速在文件中找到需要修改的地方.如我们需要修 ...

  2. 对HTTP和TCP的理解

    1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. ...

  3. [ZJOI2019]语言[树链的并、线段树合并]

    题意 题目链接 分析 考虑枚举每个点的答案,最后除以 2 即可. 可以与 \(u\) 构成合法点对 的集合 为所有经过了 \(u\) 的链的并.因为这些链两两有交,根据结论 "树上两条相交的 ...

  4. GeneXus学习笔记——入门篇

    使用GeneXus做开发做了有一段时间了 却发现一个问题(O_O)?就是除了相关的Wiki外 网上其他地方的相关资料都很少 于是乎我就想在这记录一些东西 来帮助以后会用到的人(°ー°") 那 ...

  5. 第五届CCPC河南省赛参赛有感

    10点开始,不过两次推迟了10分钟,也就是10点20开始.然后真的开始了,我还以为还会推迟10分钟. 比赛从密码输错开始,到瞎改代码疯狂提交结束. 输错密码,耽误了一点时间.点开签到题<文本修改 ...

  6. android:activity知识点

    一.活动流程 1.创建活动 public class firstActivity extends Activity{} 2.创建布局 新建first_layout.xml文件 3.注册活动 在andr ...

  7. sql server 2008 R2 配置管理工具打不开

    使用 sql server 配置管理工具是报如下错误: 解决方法:   1 找出 sqlmgmproviderxpsp2up.mof 这个文件的位置   2 以管理员身份运行 mofcomp &quo ...

  8. 在MVC程序中使用MongoDB数据库

    .net项目中混搭数据库 安装和部署 C#中使用MongoDB MongoDb与关系型数据库区别 开机自启动 关系型数据库和非关系型数据口可以混搭 MongoDB是一个高性能,开源,无模式的,基于分布 ...

  9. 时间格式为yyyymmdd的String类型的时间,计算时间间隔有错误

    时间格式类型为yyyymmdd,并且为String类型,计算时间间隔有误,一直搞不清楚是什么原因.网上百度了许多,时间格式基本都是yyyy-mm-dd这样的时间格式的,但是yyyymmdd这样的时间格 ...

  10. JavaScript设计模式-21.命令模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...