有关管道的基本用法请看System.IO之使用管道在进程间通信 (System.IO.Pipes使用)。
本文介绍命名管道使用实例,文中例子是几个客户端都通过一台服务器获得新生成的int类型id。
服务器端功能:当客户端请求一个新的id时,将现有id自增1,然后返回给客户端。
服务器端实现:在程序启动时,启动n个线程,在每个线程中都声明一个NamedPipeServerStream的实例,并循环的 WaitForConnection(),将新的id写入到命名管道中,然后断开连接。在程序退出时释放NamedPipeServerStream实例
如下代码实现:
001 |
using System;
|
002 |
using System.Collections.Generic;
|
003 |
using System.Linq;
|
004 |
using System.Text;
|
005 |
006 |
007 |
using System.IO;
|
008 |
using System.IO.Pipes;
|
009 |
using System.Threading;
|
010 |
011 |
namespace IDServer
|
012 |
{ |
013 |
class Program
|
014 |
{
|
015 |
/// <summary>
|
016 |
/// 命名管道名字
|
017 |
/// </summary>
|
018 |
private const string PIPE_NAME = "testNetworkPipe" ;
|
019 |
020 |
//定义线程数,也是NamedPipeServerStream的允许最多的实例数
|
021 |
private const int MAX_THREADS_COUNT = 3;
|
022 |
private static volatile int _runingThreadCount = 0;
|
023 |
024 |
private static volatile int _newId = 0;
|
025 |
026 |
//实例数组
|
027 |
private static NamedPipeServerStream[] _serverStreams;
|
028 |
029 |
static void Main( string [] args)
|
030 |
{
|
031 |
_serverStreams = new NamedPipeServerStream[MAX_THREADS_COUNT];
|
032 |
033 |
//在进程退出时释放所有NamedPipeServerStream实例
|
034 |
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
|
035 |
|
036 |
//启动线程
|
037 |
StartServers();
|
038 |
039 |
Console.Read();
|
040 |
}
|
041 |
042 |
/// <summary>
|
043 |
/// 在进程退出时释放命名管道
|
044 |
/// </summary>
|
045 |
/// <param name="sender"></param>
|
046 |
/// <param name="e"></param>
|
047 |
static void CurrentDomain_ProcessExit( object sender, EventArgs e)
|
048 |
{
|
049 |
if (_serverStreams != null )
|
050 |
{
|
051 |
foreach (NamedPipeServerStream item in _serverStreams)
|
052 |
{
|
053 |
item.Dispose();
|
054 |
}
|
055 |
}
|
056 |
}
|
057 |
058 |
/// <summary>
|
059 |
/// 启动服务器端线程
|
060 |
/// </summary>
|
061 |
private static void StartServers()
|
062 |
{
|
063 |
for ( int i = 0; i < MAX_THREADS_COUNT; i++)
|
064 |
{
|
065 |
Thread thread = new Thread( new ThreadStart(StartNewIDServer));
|
066 |
thread.Start();
|
067 |
}
|
068 |
}
|
069 |
070 |
071 |
/// <summary>
|
072 |
/// 启动一个NamedPipeServerStream实例
|
073 |
/// </summary>
|
074 |
private static void StartNewIDServer()
|
075 |
{
|
076 |
NamedPipeServerStream stream = null ;
|
077 |
Console.WriteLine( "start server in thread " + Thread.CurrentThread.ManagedThreadId);
|
078 |
079 |
stream = _serverStreams[_runingThreadCount] = new NamedPipeServerStream(PIPE_NAME,
|
080 |
PipeDirection.InOut,
|
081 |
MAX_THREADS_COUNT,
|
082 |
PipeTransmissionMode.Message,
|
083 |
PipeOptions.None);
|
084 |
int threadNo = _runingThreadCount;
|
085 |
_runingThreadCount += 1;
|
086 |
087 |
while ( true )
|
088 |
{
|
089 |
stream.WaitForConnection();
|
090 |
int newId = ++_newId;
|
091 |
092 |
byte [] bytes = BitConverter.GetBytes(newId);
|
093 |
stream.Write(bytes, 0, bytes.Length);
|
094 |
stream.Flush();
|
095 |
Console.Write( "threadNo:" + Thread.CurrentThread.ManagedThreadId + "\r" );
|
096 |
stream.Disconnect();
|
097 |
}
|
098 |
}
|
099 |
100 |
}
|
101 |
} |
客户端的功能是不断的发出获得新id的请求,并打印新id,在客户端可以配置服务端的服务器IP。
如下代码:
01 |
using System;
|
02 |
using System.Collections.Generic;
|
03 |
using System.Linq;
|
04 |
using System.Text;
|
05 |
using System.Threading;
|
06 |
07 |
namespace IDClient
|
08 |
{ |
09 |
class Program
|
10 |
{
|
11 |
private const string PIPE_NAME = "testNetworkPipe" ;
|
12 |
13 |
static void Main( string [] args)
|
14 |
{
|
15 |
Console.WriteLine( "请输入任何字符回车开始执行程序.." );
|
16 |
Console.Read();
|
17 |
do
|
18 |
{
|
19 |
//内网服务器ip,必须是局域网
|
20 |
string serverName = "127.0.0.1" ;
|
21 |
//声明NamedPipeClientStream实例
|
22 |
using (var clientStream = new System.IO.Pipes.NamedPipeClientStream(serverName, PIPE_NAME))
|
23 |
{
|
24 |
//连接服务器
|
25 |
clientStream.Connect(1000);
|
26 |
//设置为消息读取模式
|
27 |
clientStream.ReadMode = System.IO.Pipes.PipeTransmissionMode.Message;
|
28 |
29 |
do
|
30 |
{
|
31 |
byte [] bytes = new byte [4];
|
32 |
clientStream.Read(bytes, 0, 4);
|
33 |
int val = BitConverter.ToInt32(bytes, 0);
|
34 |
Console.Write( "NewID == " + val + "\r" );
|
35 |
} while (!clientStream.IsMessageComplete);
|
36 |
}
|
37 |
38 |
Thread.Sleep(1);
|
39 |
} while ( true );
|
40 |
}
|
41 |
}
|
42 |
} |
在sql server中就使用了命名管道在局域网内挂进程通讯。
在声明NamedPipeServerStream实例是可以指定其实例个数,如果实例数超过这个数,就会抛出“所有管道范例都在使用中”的IO异常。
本例不可以在实际项目中使用。
相关随笔:
.Net那点事儿系列:System.IO之windows文件操作
.Net那点事儿系列:System.IO之Stream
System.IO之内存映射文件共享内存
System.IO之使用管道在进程间通信 (System.IO.Pipes使用)
System.IO系列:局域网内多线程使用命名管道在进程之间通信实例
请尊重作者的劳动,转载请保留链接 玉开的技术博客
玉开的技术随笔推荐