`
jiq408694711
  • 浏览: 32830 次
  • 性别: 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# 进程间通信:命名管道方式例子 .net 2.0框架环境,进程间传递对象。

    C#与C++进程间通信

    通过命名管道实现了C#及C++进程的通信,并支持复制类型数据结构的传输.

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

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

    C#命名管道通信

    命名管道不仅可以在本机上实现两个进程间的通信,还可以跨网络实现两个进程间的通信

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

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

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

    命名管道可以用于本机的进程间或网络上不同机器进程间通信。这是一个运用命名管道进行通信的例子。包含客户端和服务器端。

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

    QT多个命名管道通信,并与C#客户端同时多个通信, 同时已有C#的客户端与服务器的通信,QT与QT的通信,QT与C#的通信,只要把管道名改为一至即可。

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

    服务端与客户端通过命名管道实现通信,收发均在子线程完成。

    命名管道通信完整实例

    MSDN上管道实现进程间通信的例子太敷衍了,由于项目中以前用的进程通信模块用的第三方在某些电脑上出现了未知bug,最后自己重新写了个进程间通信的模块在项目中使用。本例子将管道通信逻辑在PipeChanel类里实现,...

    进程通信(套接字、内存映射、命名管道)范例

    总结进程通信的三种方式 套接字、内存映射、命名管道,并且都配有范例程序

    VC++和C#管道通信(2015更新)

    本例程服务器使用VC++,客户端使用C#,两个进程通过管道通信。2015年更新,原下载地址:http://download.csdn.net/detail/dawsen/5760333

    C#命名管道服务器客户端源码

    进程间通过命名管道通信,服务器和客户端源码示例。

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

    在C#中,有多种进程间通信(Inter-Process Communication,IPC)的技术。以下是一些主要的通信方式: 1.命名管道(Named Pipes) 2.套接字(Sockets) 3.共享内存(Shared Memory) 4.信号量(Semaphore) 5.消息...

    详解Python进程间通信之命名管道

    本篇文章主要介绍了详解Python进程间通信之命名管道,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    .NET和Delphi通过命名管道进行进程间通信

    通过标准Windows命名管道从.NET应用程序调用本机方法

    pfinal-nc#LaravelTechnicalDetails#管道1

    管道目录概念知识准备命名管道参考概念管道用于存储进程之间的通信数据, 为了方便理解, 可以把管道比作文件, 进程A将数据写到管道中, 进程B从管道中读取数据.管

    完整的打印机监控源码

    它还允许在其他计算机上的应用程序与您计算机上的应用程序之间进行命名管道通信,这是用于 RPC 的。命名管道通信是为一个进程的输出(此输出用作另外一个进程的输入)而保留的内存。接受输入的进程不必是本地进程。

    memory.dll:C#黑客库,用于制作PC游戏培训师

    注入DLL并创建命名管道以与其进行通信。 有关更多信息,请参。 写入具有许多不同值类型的地址。 例如:byte,2bytes,bytes,float,int,string,double或long 可选的外部.ini文件,用于代码存储。 地址结构是...

    疯狂JAVA讲义

    1.2.1 C#简介和优势 4 1.2.2 Ruby简介和优势 4 1.2.3 Python的简介和优势 5 1.3 Java程序运行机制 5 1.3.1 高级语言的运行机制 6 1.3.2 Java程序的运行机制和JVM 6 1.4 开发Java的准备 7 1.4.1 安装JDK 8 ...

Global site tag (gtag.js) - Google Analytics