`
jiq408694711
  • 浏览: 36572 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

C#使用命名管道通过网络在进程之间进行通信

 
阅读更多

from MSDN

命名管道提供的功能比匿名管道多。其功能包括通过网络进行全双工通信和多个服务器实例;基于消息的通信;以及客户端模拟,这使得连接进程可在远程服务器上使用其自己的权限集。

下面的示例演示如何使用NamedPipeServerStream类创建命名管道。在此示例中,服务器进程创建了四个线程。每个线程可以接受一个客户端连接。连接的客户端进程随后向服务器提供一个文件名。如果客户端具有足够的权限,服务器进程就会打开文件并将其内容发送回客户端。

using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;

public class PipeServer
{
    private static int numThreads = 4;

    public static void Main()
    {
        int i;
        Thread[] servers = new Thread[numThreads];

        Console.WriteLine("\n*** Named pipe server stream with impersonation example ***\n");
        Console.WriteLine("Waiting for client connect...\n");
        for (i = 0; i < numThreads; i++)
        {
            servers[i] = new Thread(ServerThread);
            servers[i].Start();
        }
        Thread.Sleep(250);
        while (i > 0)
        {
            for (int j = 0; j < numThreads; j++)
            {
                if (servers[j] != null)
                {
                    if (servers[j].Join(250))
                    {
                        Console.WriteLine("Server thread[{0}] finished.", servers[j].ManagedThreadId);
                        servers[j] = null;
                        i--;    // decrement the thread watch count
                    }
                }
            }
        }
        Console.WriteLine("\nServer threads exhausted, exiting.");
    }

    private static void ServerThread(object data)
    {
        NamedPipeServerStream pipeServer =
            new NamedPipeServerStream("testpipe", PipeDirection.InOut, numThreads);

        int threadId = Thread.CurrentThread.ManagedThreadId;

        // Wait for a client to connect
        pipeServer.WaitForConnection();

        Console.WriteLine("Client connected on thread[{0}].", threadId);
        try
        {
            // Read the request from the client. Once the client has
            // written to the pipe its security token will be available.

            StreamString ss = new StreamString(pipeServer);

            // Verify our identity to the connected client using a
            // string that the client anticipates.

            ss.WriteString("I am the one true server!");
            string filename = ss.ReadString();

            // Read in the contents of the file while impersonating the client.
            ReadFileToStream fileReader = new ReadFileToStream(ss, filename);

            // Display the name of the user we are impersonating.
            Console.WriteLine("Reading file: {0} on thread[{1}] as user: {2}.",
                filename, threadId, pipeServer.GetImpersonationUserName());
            pipeServer.RunAsClient(fileReader.Start);
        }
        // Catch the IOException that is raised if the pipe is broken
        // or disconnected.
        catch (IOException e)
        {
            Console.WriteLine("ERROR: {0}", e.Message);
        }
        pipeServer.Close();
    }
}

// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
    private Stream ioStream;
    private UnicodeEncoding streamEncoding;

    public StreamString(Stream ioStream)
    {
        this.ioStream = ioStream;
        streamEncoding = new UnicodeEncoding();
    }

    public string ReadString()
    {
        int len = 0;

        len = ioStream.ReadByte() * 256;
        len += ioStream.ReadByte();
        byte[] inBuffer = new byte[len];
        ioStream.Read(inBuffer, 0, len);

        return streamEncoding.GetString(inBuffer);
    }

    public int WriteString(string outString)
    {
        byte[] outBuffer = streamEncoding.GetBytes(outString);
        int len = outBuffer.Length;
        if (len > UInt16.MaxValue)
        {
            len = (int)UInt16.MaxValue;
        }
        ioStream.WriteByte((byte)(len / 256));
        ioStream.WriteByte((byte)(len & 255));
        ioStream.Write(outBuffer, 0, len);
        ioStream.Flush();

        return outBuffer.Length + 2;
    }
}

// Contains the method executed in the context of the impersonated user
public class ReadFileToStream
{
    private string fn;
    private StreamString ss;

    public ReadFileToStream(StreamString str, string filename)
    {
        fn = filename;
        ss = str;
    }

    public void Start()
    {
        string contents = File.ReadAllText(fn);
        ss.WriteString(contents);
    }
}

下面的示例演示使用NamedPipeClientStream类的客户端进程。客户端连接服务器进程并向服务器发送一个文件名。该示例使用模拟,所以运行客户端应用程序的标识必须具有访问文件的权限。服务器随后将文件内容发送回客户端。文件内容随后显示在控制台上。

using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Security.Principal;
using System.Diagnostics;
using System.Threading;

public class PipeClient
{
    private static int numClients = 4;

    public static void Main(string[] Args)
    {
        if (Args.Length > 0)
        {
            if (Args[0] == "spawnclient")
            {
                NamedPipeClientStream pipeClient =
                    new NamedPipeClientStream(".", "testpipe",
                        PipeDirection.InOut, PipeOptions.None,
                        TokenImpersonationLevel.Impersonation);

                Console.WriteLine("Connecting to server...\n");
                pipeClient.Connect();

                StreamString ss = new StreamString(pipeClient);
                // Validate the server's signature string
                if (ss.ReadString() == "I am the one true server!")
                {
                    // The client security token is sent with the first write.
                    // Send the name of the file whose contents are returned
                    // by the server.
                    ss.WriteString("c:\\textfile.txt");

                    // Print the file to the screen.
                    Console.Write(ss.ReadString());
                }
                else
                {
                    Console.WriteLine("Server could not be verified.");
                }
                pipeClient.Close();
                // Give the client process some time to display results before exiting.
                Thread.Sleep(4000);
            }
        }
        else
        {
            Console.WriteLine("\n*** Named pipe client stream with impersonation example ***\n");
            StartClients();
        }
    }

    // Helper function to create pipe client processes
    private static void StartClients()
    {
        int i;
        string currentProcessName = Environment.CommandLine;
        Process[] plist = new Process[numClients];

        Console.WriteLine("Spawning client processes...\n");

        if (currentProcessName.Contains(Environment.CurrentDirectory))
        {
            currentProcessName = currentProcessName.Replace(Environment.CurrentDirectory, String.Empty);
        }

        // Remove extra characters when launched from Visual Studio
        currentProcessName = currentProcessName.Replace("\\", String.Empty);
        currentProcessName = currentProcessName.Replace("\"", String.Empty);

        for (i = 0; i < numClients; i++)
        {
            // Start 'this' program but spawn a named pipe client.
            plist[i] = Process.Start(currentProcessName, "spawnclient");
        }
        while (i > 0)
        {
            for (int j = 0; j < numClients; j++)
            {
                if (plist[j] != null)
                {
                    if (plist[j].HasExited)
                    {
                        Console.WriteLine("Client process[{0}] has exited.",
                            plist[j].Id);
                        plist[j] = null;
                        i--;    // decrement the process watch count
                    }
                    else
                    {
                        Thread.Sleep(250);
                    }
                }
            }
        }
        Console.WriteLine("\nClient processes finished, exiting.");
    }
}

// Defines the data protocol for reading and writing strings on our stream
public class StreamString
{
    private Stream ioStream;
    private UnicodeEncoding streamEncoding;

    public StreamString(Stream ioStream)
    {
        this.ioStream = ioStream;
        streamEncoding = new UnicodeEncoding();
    }

    public string ReadString()
    {
        int len;
        len = ioStream.ReadByte() * 256;
        len += ioStream.ReadByte();
        byte[] inBuffer = new byte[len];
        ioStream.Read(inBuffer, 0, len);

        return streamEncoding.GetString(inBuffer);
    }

    public int WriteString(string outString)
    {
        byte[] outBuffer = streamEncoding.GetBytes(outString);
        int len = outBuffer.Length;
        if (len > UInt16.MaxValue)
        {
            len = (int)UInt16.MaxValue;
        }
        ioStream.WriteByte((byte)(len / 256));
        ioStream.WriteByte((byte)(len & 255));
        ioStream.Write(outBuffer, 0, len);
        ioStream.Flush();

        return outBuffer.Length + 2;
    }
}

此示例中的客户端进程和服务器进程预期在同一台计算机上运行,因此提供给NamedPipeClientStream对象的服务器名称是"."如果客户端进程和服务器进程位于不同的计算机上,则应该用运行服务器进程的计算机的网络名称来替换"."
分享到:
评论

相关推荐

    C# 进程间通信:命名管道方式例子

    本文将深入探讨C#中使用命名管道进行进程间通信(IPC)的技术细节,并通过一个具体的实例来演示其实现。 命名管道是一种在操作系统内核中创建的特殊文件,允许不同进程之间通过读写操作进行通信。在Windows系统中,...

    C#命名管道通信,与QT命名管道通信

    命名管道通信,与QT命名管道通信,C#与C#的通信

    C# 命名管道通信 NamedPipe 进程间通信

    C# NamedPipe 通信,管道通信。 目前还有些BUG ,但是用作程序间的数据通信,问题应该不大,建议用于 Json 通信。 做这玩意出来,起初想法是用作 winService 和 winform 的通信,可以通过winfrom 上的操作,来控制...

    QT进程多个管道通信,并与C#客户端同时多个通信

    总之,通过理解和应用QT的命名管道机制,开发者可以构建出高效、可扩展的多进程通信系统,同时能够与其他语言的应用(如C#)无缝对接,提升系统的整体性能和灵活性。在设计这样的系统时,应充分考虑并发控制、数据...

    C#与C++进程间通信

    命名管道是一种在操作系统中提供半双工或全双工通信的机制,适用于在同一台计算机上的进程间通信,也可用于网络通信。在Windows系统中,命名管道被广泛用于不同进程间的通信,尤其是跨语言的通信场景,如C#和C++。 ...

    C#命名管道通信

    以下是一个简单的C#命名管道通信示例: ```csharp // 服务器端 using System; using System.IO.Pipes; class PipeServer { static void Main() { NamedPipeServerStream pipeServer = new NamedPipeServerStream...

    C# 命名管道通信源码

    命名管道是Windows操作系统中进程间通信(IPC,Inter-Process Communication)的一种方式,它允许不同进程之间通过共享内存进行高效的数据传输。在C#中,我们可以利用.NET框架提供的命名管道类来实现这一功能。本...

    一个命名管道通信示例,包含客户端和服务器端

    命名管道是Windows操作系统提供的一种进程间通信(IPC,Inter-Process Communication)机制,它允许同一台计算机上的不同进程或者在局域网内的不同计算机之间进行数据交换。在本示例中,我们有两个主要的组成部分:...

    C# 命名管道 异步通信的例子

    总结起来,这个例子是一个实用的C#命名管道异步通信示例,它演示了如何在两个独立的应用之间高效且非阻塞地传递数据。对于任何想要学习C#进程间通信,尤其是希望使用异步机制的人来说,这是一个非常有价值的参考资料...

    C--和C#进程之间通过命名管道通信(上).doc

    ### C++和C#进程之间通过命名管道通信详解 #### 一、命名管道简介 **命名管道**(Named Pipe)是一种进程间通信(IPC)机制,允许不同进程间进行可靠的数据传输。它不仅可以在同一台计算机上的不同进程之间工作,...

    多线程全双工命名管道实现进程通信

    标题中的“多线程全双工命名管道实现进程通信”是指在编程中使用多线程技术结合命名管道来实现不同进程间的双向通信。这是一种高效、可靠的数据交换方式,尤其适用于在同一台计算机上运行的多个程序之间。 命名管道...

    C#进程间通信-管道代码实例

    本文将深入探讨C#中的管道进程间通信,并通过一个具体的代码实例进行解析。 首先,管道通信是一种半双工(即数据只能单向流动)的数据通信方式,可以用于同一台机器上的不同进程之间,甚至在不同的网络节点之间。C#...

    C# 进程间通信 命名通道

    在.NET框架中,C#提供了一种进程间通信(IPC,Inter-Process Communication)的方式——命名管道(Named Pipe)。命名管道是一种高效的通信机制,允许不同的进程在同一台计算机上相互通信,甚至可以在不同用户会话...

    c#异步命名管道以及demo

    命名管道是一种进程间通信(IPC)机制,允许在同一台计算机上的不同进程之间交换数据。本篇将深入探讨C#中的异步命名管道及其在实际应用中的实现。 首先,我们要理解什么是异步编程。在C#中,异步编程是通过`async`...

    进程通讯、命名管道、一对多连接

    在IT领域,进程通信是操作系统中的重要概念,它允许不同进程之间交换数据和信息,以协同完成复杂的任务。本文将深入探讨"进程通讯"、"命名管道"以及"一对多连接"这三个关键知识点。 首先,我们要理解什么是"进程...

    c++与c#命名管道

    在C++和C#之间使用命名管道进行通信,可以实现高效且低延迟的数据交换,尤其适用于在同一台计算机上运行的进程间通信。然而,跨网络的通信可能需要其他机制,如TCP/IP套接字。对于更复杂的需求,可以研究Windows消息...

    c#进程之间通信,c#exe 之间发消息,c#exe 相互通信

    在C#编程中,进程间通信(IPC,Inter-Process Communication)是实现不同应用程序或同一计算机上多个执行单元之间共享数据、同步操作的关键技术。在VS2005环境下,开发者可以利用各种IPC机制实现C# EXE之间的消息...

    Windows 命名管道进进程过程调用

    命名管道是Windows IPC机制的一种,它允许不同进程之间进行半双工(即数据只能单向流动)的通信。本文将深入探讨命名管道的工作原理、创建与使用方法,以及如何通过进程过程调用(RPC,Remote Procedure Call)...

    C#_命名管道_简单示例.zip

    用命名管道实现进程间通信,界面用的wpf。 客户端输入 例:1+1,点击send(点Send前请打开服务端) 服务端接收到并运算后将结果返回给客户端 vs2015 + .NET Framework4.5.2,Windows应用程序

    C#进程间通信之共享内存

    本文将重点探讨在C#环境中如何利用共享内存进行进程间通信,这对于理解和优化多进程应用的性能至关重要。 共享内存是一种高效的IPC机制,它允许多个进程直接读写同一块内存区域,而无需通过任何中间媒介。在C#中,...

Global site tag (gtag.js) - Google Analytics