程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# NamePipe使用小結

C# NamePipe使用小結

編輯:C#入門知識

C# NamePipe使用小結


最近在一次項目中使用到了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類型。當然也可以傳遞其他類型的內容。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved