C#中进程间的通信:管道

    程序中有两个进程,并且一个进程需要和另一个进程进行通信,那么可以使用管道,所谓的C/S模式也和这个差不多。

    分为两端服务和客户端,下面简单说一下管道通信。两个类Server和Client,都包含如下方法:监听,接收,发送。

如下类:

Server类

    public class Server
    {
        [DllImport("kernel32.dll", SetLastError = true)]

        public static extern SafeFileHandle CreateNamedPipe(

           String pipeName,

           uint dwOpenMode,

           uint dwPipeMode,

           uint nMaxInstances,

           uint nOutBufferSize,

           uint nInBufferSize,

           uint nDefaultTimeOut,

           IntPtr lpSecurityAttributes);

        [DllImport("kernel32.dll", SetLastError = true)]

        public static extern int ConnectNamedPipe(

           SafeFileHandle hNamedPipe,

           IntPtr lpOverlapped);

        public const uint DUPLEX = (0x00000003);

        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);

        public class Client
        {
            public SafeFileHandle handle;

            public FileStream stream;
        }

        public delegate void MessageReceivedHandler(Client client, string message);

        public event MessageReceivedHandler MessageReceived;

        public const int BUFFER_SIZE = 4096;

        string pipeName;

        Thread listenThread;

        bool running;

        List<Client> clients;

        public string PipeName
        {
            get { return this.pipeName; }

            set { this.pipeName = value; }
        }

        public bool Running
        {
            get { return this.running; }
        }

        public Server()
        {
            this.clients = new List<Client>();
        }

        public void Start()
        {
            this.listenThread = new Thread(new ThreadStart(ListenForClients));

            this.listenThread.Start();

            this.running = true;
        }

        private void ListenForClients()
        {
            while (true)
            {
                SafeFileHandle clientHandle =

                CreateNamedPipe(

                     this.pipeName,

                     DUPLEX | FILE_FLAG_OVERLAPPED,

                     0,

                     255,

                     BUFFER_SIZE,

                     BUFFER_SIZE,

                     0,

                     IntPtr.Zero);

                if (clientHandle.IsInvalid)

                    return;

                int success = ConnectNamedPipe(clientHandle, IntPtr.Zero);

                if (success == 0)

                    return;

                Client client = new Client();

                client.handle = clientHandle;

                lock (clients)

                    this.clients.Add(client);

                Thread readThread = new Thread(new ParameterizedThreadStart(Read));

                readThread.Start(client);
            }
        }

        private void Read(object clientObj)
        {
            Client client = (Client)clientObj;

            client.stream = new FileStream(client.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);

            byte[] buffer = new byte[BUFFER_SIZE];

            //ASCIIEncoding encoder = new ASCIIEncoding();

            UTF8Encoding encoder = new UTF8Encoding();//可以传汉字

            while (true)
            {
                int bytesRead = 0;

                try
                {
                    bytesRead = client.stream.Read(buffer, 0, BUFFER_SIZE);
                }
                catch
                {
                    break;
                }

                if (bytesRead == 0)

                    break;


                if (this.MessageReceived != null)

                    this.MessageReceived(client, encoder.GetString(buffer, 0, bytesRead));
            }
            client.stream.Close();

            client.handle.Close();

            lock (this.clients)

                this.clients.Remove(client);
        }

        public void SendMessage(string message)
        {
            lock (this.clients)
            {
                ASCIIEncoding encoder = new ASCIIEncoding();

                byte[] messageBuffer = encoder.GetBytes(message);

                foreach (Client client in this.clients)
                {
                    client.stream.Write(messageBuffer, 0, messageBuffer.Length);

                    client.stream.Flush();
                }
            }
        }
    }

Client类

    public class Client
    {
        [DllImport("kernel32.dll", SetLastError = true)]

        public static extern SafeFileHandle CreateFile(

           String pipeName,

           uint dwDesiredAccess,

           uint dwShareMode,

           IntPtr lpSecurityAttributes,

           uint dwCreationDisposition,

           uint dwFlagsAndAttributes,

           IntPtr hTemplate);

        public const uint GENERIC_READ = (0x80000000);

        public const uint GENERIC_WRITE = (0x40000000);

        public const uint OPEN_EXISTING = 3;

        public const uint FILE_FLAG_OVERLAPPED = (0x40000000);

        public delegate void MessageReceivedHandler(string message);

        public event MessageReceivedHandler MessageReceived;

        public const int BUFFER_SIZE = 4096;

        string pipeName;

        private FileStream stream;

        private SafeFileHandle handle;

        Thread readThread;

        bool connected;

        public bool Connected
        {
            get { return this.connected; }
        }

        public string PipeName
        {
            get { return this.pipeName; }

            set { this.pipeName = value; }
        }

        public void Connect()
        {
            this.handle =

               CreateFile(

                  this.pipeName,

                  GENERIC_READ | GENERIC_WRITE,

                  0,

                  IntPtr.Zero,

                  OPEN_EXISTING,

                  FILE_FLAG_OVERLAPPED,

                  IntPtr.Zero);

            if (this.handle.IsInvalid)

                return;

            this.connected = true;

            this.stream = new FileStream(this.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);

            this.readThread = new Thread(new ThreadStart(Read));

            this.readThread.Start();
        }


        public void Read()
        {
            byte[] readBuffer = new byte[BUFFER_SIZE];

            ASCIIEncoding encoder = new ASCIIEncoding();

            while (true)
            {
                int bytesRead = 0;

                try
                {
                    bytesRead = this.stream.Read(readBuffer, 0, BUFFER_SIZE);
                }
                catch
                {
                    break;
                }

                if (bytesRead == 0)
                    break;

                if (this.MessageReceived != null)

                    this.MessageReceived(encoder.GetString(readBuffer, 0, bytesRead));
            }
            this.stream.Close();

            this.handle.Close();
        }

        public void SendMessage(string message)
        {
            //ASCIIEncoding encoder = new ASCIIEncoding();

            UTF8Encoding encoder = new UTF8Encoding();//可以传汉字

            byte[] messageBuffer = encoder.GetBytes(message);

            this.stream.Write(messageBuffer, 0, messageBuffer.Length);

            this.stream.Flush();
        }
    }

Server端

    public class ServerPort
    {
        private Delegate sendMessage = null;

        private ContainerControl mainForm;

        public Server pipeServer = null;

        public ServerPort(ContainerControl form,Delegate sendmessage)
        {
            mainForm = form;

            sendMessage = sendmessage;
        }

        void SendMsg(string msg)
        {
            this.mainForm.Invoke(sendMessage, new Object[] { msg });
        }

        void PipeServer_MessageReceived(Server.Client client, string message)
        {
            if (!message.Equals(""))
            {
                SendMsg("接收到的信息是:" + message);
            }
            else
            {
                SendMsg("消息未收到???");
            }
        }

        private void MessageSend()
        {

        }

        public void PipServerStart()
        {
            try
            {
                if (!this.pipeServer.Running)
                {
                    this.pipeServer.PipeName = "\\\\.\\pipe\\testprocesspipe";

                    this.pipeServer.Start();

                    this.pipeServer.MessageReceived += new Server.MessageReceivedHandler(PipeServer_MessageReceived);
                }
            }
            catch
            {
            }
        }
    }

Client端,发送信息

    public class ClientPort
    {
        private static Client pipeClient; 

        public static void MessagePipeStart()
        {
            if (pipeClient == null)
            {
                pipeClient = new Client();

                pipeClient.MessageReceived += new Client.MessageReceivedHandler(pipeClient_MessageReceived);
            }

            if (!pipeClient.Connected)
            {
                pipeClient.PipeName = "\\\\.\\pipe\\testprocesspipe";

                pipeClient.Connect();
            }

            if (pipeClient != null && pipeClient.Connected)
            {
                MessageSend("测试传输的字符:金胖子死了!!!");
            }
        }

        static void MessageSend(string str)
        {
            pipeClient.SendMessage(str);
        }

        static void pipeClient_MessageReceived(string message)
        {

        }
    }

启动服务端

            ServerPort serverPort;

            recivedMessage += new ServerRecivedMessageDelegate(DisplayMessage);

            try
            {
                serverPort = new ServerPort(this, recivedMessage);

                serverPort.pipeServer = new Server();

                serverPort.PipServerStart();

            }
            catch
            { }

客户端发送信息

            ClientPort.MessagePipeStart();

接收如图,

客户端发送后,服务端监听到,并接收

 

简单的例子下载地址:http://download.csdn.net/detail/yysyangyangyangshan/3946892

   上述 只是在一个工程中简单的模拟。正的进程的通信,Server端和Client端分别在两个进程中,启动的方式都一样,当两端都启动的话,就可以互发信息了。当然,PipeName必须一致,双方才能接收到对方的信息。

    这样,可以建造一个服务端,启动好几个Server设置PipeName 各不同,然后客户端分别对应不同的PipeName,就可实现服务器一对多的通信。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值