之前看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. 【Hadoop & Ecilpse】Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: user=bruce, access=WRITE, inode="/out2/_temporary/0":atguigu:supergroup:drwxr-xr-x

    问题再现: 使用本机 Ecilpse  (Windows环境) 去访问远程 hadoop 集群出现以下异常: 问题原因: 因为远程提交的情况下如果没有 hadoop 的系统环境变量,就会读取当前主机的 ...

  2. Linux之Ubuntu系统安装搜狗输入法

    如何在Ubuntu系统中安装搜狗输入法? 1.第一步  下载搜狗输入法文件for Linux 2.检查更新 update 如果没有更新的话,需要做这一步 3.语言支持 选择fcitx,然后关闭界面 4 ...

  3. week 4 Vocabulary in paper

    1.Using action verbs 1.1 deffenence between action verbs and fuzzy verbs Action verbs(strong verbs) ...

  4. 钉钉机器人集成Jenkins推送消息模板自定义发送报告

    一.由于公司同样也使用了钉钉.那么在做Jenkins集成自动化部署的时候,也是可以集成钉钉的. 那种Jenkins下载钉钉插件集成,简单设置就可以完成了.我们今天要做的是,定制化的发送消息. 钉钉推送 ...

  5. PHP下的浮点运算不准的解决办法

    首先看一段代码: 首先看一段代码: <?php $a = 0.1; $b = 0.7; var_dump(($a + $b) == 0.8); 打印出来的值居然为 boolean false P ...

  6. 数据结构:广义表的实现(Java)

    广义表的简单理解在这篇博文中:https://blog.csdn.net/lishanleilixin/article/details/87364496,在此不做赘述. Java实现广义表: pack ...

  7. Description &&debugDescription && runtime(debug模式下调试model)

    description 在开发过程中, 往往会有很多的model来装载属性. 而在开发期间经常会进行调试查看model里的属性值是否正确. 那么问题来了, 在objective-c里使用NSLog(& ...

  8. 介绍&代码

    之前参考前辈实现的分页组件,还ok. 介绍: 基于Web,实现分页样式 和 控制页面内容数据的展示形式. 实现: from django.utils.safestring import mark_sa ...

  9. 【ORACLE】ORACLE session(会话)管理

    #查看当前不为空的连接select * from v$session where username is not null #查看不同用户的连接数 select username,count(user ...

  10. (转载)IDEA新建项目时,没有Spring Initializr选项

    最近开始使用IDEA作为开发工具,然后也是打算开始学习使用spring boot. 看着博客来进行操作上手spring boot,很多都是说 创建一个新项目(Create New Project) 选 ...