C# NamePipe使用小结 – Yang-Fei

最近在一次项目中使用到了C#中命名管道,所以在此写下一篇小结备忘。

为什么要使用命名管道呢?为了实现两个程序之间的数据交换。假设下面一个场景。在同一台PC上,程序A与程序B需要进行数据通信,此时我们就可以使用命名管道技术来实现。命名管道的两个对象。NamedPipeClientStream NamedPipeServerStream 对象。请求通信的一方为Client端,发送数据的一方为Server端。

使用NamedPipe来通信,如果Server端崩溃了,不会影响到客户端。

下面我们通过一个例子来说明:

Server端:

UI:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”*”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”Auto”/>
<ColumnDefinition Width=”*”/>
</Grid.ColumnDefinitions>

<TextBlock Text=”Received Message:” Grid.Row=”1″ Margin=”10″/>
<TextBlock x:Name=”tblRecMsg” VerticalAlignment=”Center” Grid.Row=”1″ Grid.Column=”1″/>

<Button Content=”Send” Grid.Row=”2″ Margin=”10″ Click=”OnSend”/>
<TextBox x:Name=”txtSendMsg” VerticalAlignment=”Center” Grid.Row=”2″ Grid.Column=”1″ Margin=”10″/>
</Grid>

Code:

private NamedPipeServerStream _pipe;

private const string PipeName = PipeSample;

private const int PipeInBufferSize = 4096;

private const int PipeOutBufferSize = 65535;

private Encoding encoding = Encoding.UTF8;

public MainWindow()
{
InitializeComponent();

_pipe = new NamedPipeServerStream
(
PipeName,
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous | PipeOptions.WriteThrough,
PipeInBufferSize,
PipeOutBufferSize
);

_pipe.BeginWaitForConnection(WaitForConnectionCallback, _pipe);
}

private void WaitForConnectionCallback(IAsyncResult ar)
{
var pipeServer = (NamedPipeServerStream)ar.AsyncState;

pipeServer.EndWaitForConnection(ar);

var data = new byte[PipeInBufferSize];

var count = pipeServer.Read(data, 0, PipeInBufferSize);

if (count > 0)
{
// 通信双方可以约定好传输内容的形式,例子中我们传输简单文本信息。

string message = encoding.GetString(data, 0, count);

Dispatcher.BeginInvoke(new Action(() =>
{
tblRecMsg.Text = message;
}));
}
}

private void OnSend(object sender, RoutedEventArgs e)
{
if (_pipe.IsConnected)
{
try
{
string message = txtSendMsg.Text;

byte[] data = encoding.GetBytes(message);

_pipe.Write(data, 0, data.Length);
_pipe.Flush();
_pipe.WaitForPipeDrain();
}
catch { }
}

Close();
}

Client端:

UI:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”*”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=”Auto”/>
<ColumnDefinition Width=”*”/>
</Grid.ColumnDefinitions>

<Button Content=”Connect” Margin=”10″ Click=”OnConnect”/>

<TextBlock Text=”Received Message:” Grid.Row=”1″ Margin=”10″/>
<TextBlock x:Name=”tblRecMsg” Grid.Row=”1″ Grid.Column=”1″/>
</Grid>

Code:

private const string PipeServerName = PipeServer.exe;

private const string PipeName = PipeSample;

private Encoding encoding = Encoding.UTF8;

private NamedPipeClientStream _pipe;

private bool _starting = false;

public MainWindow()
{
InitializeComponent();
}

private void OnConnect(object sender, RoutedEventArgs e)
{
if (_starting)
{
return;
}

var path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, PipeServerName);

var startInfo = new ProcessStartInfo(path)
{
UseShellExecute = false,
CreateNoWindow = true
};

try
{
var process = Process.Start(startInfo);

_pipe = new NamedPipeClientStream
(
.,
PipeName,
PipeDirection.InOut,
PipeOptions.Asynchronous | PipeOptions.WriteThrough
);

_pipe.Connect();

_pipe.ReadMode = PipeTransmissionMode.Message;

string message = Connected!;

byte[] data = encoding.GetBytes(message);

_pipe.BeginWrite(data, 0, data.Length, PipeWriteCallback, _pipe);

_starting = true;
}
catch (Exception ex)
{
Debug.Write(ex.StackTrace);
}
}

private void PipeWriteCallback(IAsyncResult ar)
{
var pipe = (NamedPipeClientStream)ar.AsyncState;

pipe.EndWrite(ar);
pipe.Flush();
pipe.WaitForPipeDrain();

var data = new byte[65535];

var count = pipe.Read(data, 0, data.Length);

if (count > 0)
{
string message = encoding.GetString(data, 0, count);

Dispatcher.BeginInvoke(new Action(() => {
tblRecMsg.Text = message;
}));
}
}

需要注意的地方:因为我们在同一台PC上面进行通信,我们只需要将 NamedPipeClientStream 构造参数中pipeServer设为”.”即可。另外因为这只是一个示例,所以PipeServer中只传递简单String类型。当然也可以传递其他类型的内容。

运行效果:

感谢您的阅读!

本文链接:C# NamePipe使用小结,转载请注明。



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量