• 采用管道进行通讯的例子


    作者:肖波
        用Remoting做进程间通讯,效率较低,于是做了一个采用管道技术进行进程间通讯的例子,在1.8G 双核计算机上每秒钟可以发送180M数据。下面给出源码
       
        Server端的管道类

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Pipe.Win32;

    namespace Pipe.Server
    {
        public delegate void ReceiveMessageFunc(System.IO.MemoryStream m);
        public delegate void ReceiveMessageErrorFunc(Exception e);

        public class PipeServer : IDisposable
        {
            enum State
            {
                Idle = 0,
                Begining = 1,
                Reading = 2,
            }

            String m_PipeName;
            uint m_Handle;
            uint m_BufferSize;
            State m_State = State.Idle;

            const ulong SYNC_HEAD = 0xf8c7a1ca13db307e;
            const uint NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;
            const int DEFAULT_BUFFER_SIZE = 1024;

            ReceiveMessageFunc m_ReceiveMessage;
            ReceiveMessageErrorFunc m_ReceiveMessageError;

            public ReceiveMessageFunc OnReceiveMessage
            {
                get
                {
                    return m_ReceiveMessage;
                }

                set
                {
                    m_ReceiveMessage = value;
                }
            }

            public ReceiveMessageErrorFunc OnReceiveMessageError
            {
                get
                {
                    return m_ReceiveMessageError;
                }

                set
                {
                    m_ReceiveMessageError = value;
                }
            }

            public String PipeName
            {
                get
                {
                    return m_PipeName;
                }
            }

            public uint BufferSize
            {
                get
                {
                    return m_BufferSize;
                }
            }

            public String PipeUri
            {
                get
                {
                    return @"\.pipe" + m_PipeName;
                }
            }

            private bool IsSyncHead(byte[] buf, uint len, out int msgLen)
            {
                msgLen = 0;

                if (len != 12)
                {
                    return false;
                }

                if (SYNC_HEAD != BitConverter.ToUInt64(buf, 0))
                {
                    return false;
                }

                msgLen = BitConverter.ToInt32(buf, sizeof(ulong));

                if (msgLen < 0)
                {
                    return false;
                }

                return true;
            }

            private void ProcessMessage(System.IO.MemoryStream m)
            {
                if (OnReceiveMessage != null)
                {
                    m.Position = 0;
                    OnReceiveMessage(m);
                }
            }

            private void ThreadProc()
            {
            }

            public PipeServer(String pipeName)
            {
                m_PipeName = pipeName;
                m_BufferSize = DEFAULT_BUFFER_SIZE;
            }

            public PipeServer(String pipeName, uint bufferSize)
            {
                m_PipeName = pipeName;
                m_BufferSize = bufferSize;
            }


            public void Listen()
            {
                while (true)
                {
                    try
                    {

                        m_Handle = NTKernel.CreateNamedPipe(PipeUri, (uint)FileAccess.PIPE_ACCESS_DUPLEX,
                            (uint)PipeMode.PIPE_READMODE_MESSAGE | (uint)PipeMode.PIPE_TYPE_MESSAGE | (uint)PipeMode.PIPE_WAIT,
                            NTKernel.PIPE_UNLIMITED_INSTANCES, m_BufferSize, m_BufferSize, NMPWAIT_USE_DEFAULT_WAIT, new SecurityAttributes());

                        if (m_Handle == NTKernel.INVAILD_HANDLE)
                        {
                            throw new Exception(String.Format("CreateNamedPipe fail, err={0}", NTKernel.GetLastError()));
                        }

                        if (!NTKernel.ConnectNamedPipe(m_Handle, IntPtr.Zero))
                        {
                            uint err = NTKernel.GetLastError();
                            NTKernel.CloseHandle(m_Handle);
                            throw new Exception(String.Format("ConnectNamedPipe fail, err={0}", err));
                        }

                        byte[] buf = new byte[m_BufferSize];

                        uint relSize = 0;
                        int msgLen = 0;
                        int offset = 0;
                        System.IO.MemoryStream m = new System.IO.MemoryStream();

                        while (NTKernel.ReadFile(m_Handle, buf, m_BufferSize, out relSize, IntPtr.Zero))
                        {
                            switch (m_State)
                            {
                                case State.Idle:
                                    if (IsSyncHead(buf, relSize, out msgLen))
                                    {
                                        m_State = State.Begining;
                                    }

                                    break;
                                case State.Begining:
                                    offset = 0;
                                    m = new System.IO.MemoryStream();
                                    m.Write(buf, 0, (int)relSize);
                                    offset += (int)relSize;
                                    if (offset >= msgLen)
                                    {
                                        m_State = State.Idle;

                                        if (offset == msgLen)
                                        {
                                            ProcessMessage(m);
                                        }
                                        else
                                        {
                                            if (OnReceiveMessageError != null)
                                            {
                                                OnReceiveMessageError(new Exception("Message overflow!"));
                                            }
                                        }

                                    }
                                    else
                                    {
                                        m_State = State.Reading;
                                    }

                                    break;
                                case State.Reading:
                                    m.Write(buf, 0, (int)relSize);
                                    offset += (int)relSize;
                                    if (offset >= msgLen)
                                    {
                                        m_State = State.Idle;

                                        if (offset == msgLen)
                                        {
                                            ProcessMessage(m);
                                        }
                                        else
                                        {
                                            if (OnReceiveMessageError != null)
                                            {
                                                OnReceiveMessageError(new Exception("Message overflow!"));
                                            }
                                        }
                                    }

                                    break;

                            }


                        }


                        NTKernel.DisconnectNamedPipe(m_Handle);
                        NTKernel.CloseHandle(m_Handle);
                        System.Threading.Thread.Sleep(10);
                    }
                    catch (Exception e)
                    {
                        if (OnReceiveMessageError != null)
                        {
                            OnReceiveMessageError(e);
                        }
                    }
                }
            }

            public void Dispose()
            {
                lock (this)
                {
                    if (m_Handle != NTKernel.INVAILD_HANDLE)
                    {
                        NTKernel.CloseHandle(m_Handle);
                        m_Handle = NTKernel.INVAILD_HANDLE;
                    }
                }
            }

            ~PipeServer()
            {
                Dispose();
            }
        }

    }


    Client 端的管道类

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    using Pipe.Win32;

    namespace Pipe.Client
    {
        public class PipeClient : IDisposable
        {
            String m_PipeName;
            String m_ComputerName;
            uint m_Handle;
            uint m_BufferSize;
            const ulong SYNC_HEAD = 0xf8c7a1ca13db307e;
            byte[] m_SendBuf;

            Propertys

            private void Connect()
            {
                int file_not_find_times = 0;

                while (true)
                {
                    m_Handle = NTKernel.CreateFile(PipeUri, (uint)FileAccess.GENERIC_READ | (uint)FileAccess.GENERIC_WRITE,
                        0, new SecurityAttributes(), (uint)CreateMode.OPEN_EXISTING, 0, 0);

                    if (m_Handle == NTKernel.INVAILD_HANDLE)
                    {
                        uint err = NTKernel.GetLastError();

                        if (err == NTKernel.ERROR_FILE_NOT_FOUND)
                        {
                            if (file_not_find_times++ < 2000)
                            {
                                System.Threading.Thread.Sleep(20);
                                continue;
                            }
                        }

                        if (err == NTKernel.ERROR_PIPE_BUSY)
                        {
                            NTKernel.WaitNamedPipeA(PipeUri, 20);
                            continue;
                        }
                        else
                        {
                            throw new Exception(String.Format("Create File for pipe fail, err={0}", NTKernel.GetLastError()));
                        }
                    }

                    break;
                }

            }

            private void WriteBuf(byte[] buf)
            {
                uint relSize;

                if (!NTKernel.WriteFile(m_Handle, buf, (uint)buf.Length, out relSize, IntPtr.Zero))
                {
                    throw new Exception(String.Format("Send message to pipe fail, err={0}", NTKernel.GetLastError()));
                }
            }

            public void Close()
            {
                lock (this)
                {
                    if (m_Handle != NTKernel.INVAILD_HANDLE)
                    {
                        bool ret = NTKernel.CloseHandle(m_Handle);
                        m_Handle = NTKernel.INVAILD_HANDLE;
                    }
                }
            }

            public PipeClient(String pipeName, uint bufferSize)
            {
                m_PipeName = pipeName;
                m_BufferSize = bufferSize;
                m_Handle = NTKernel.INVAILD_HANDLE;
                m_SendBuf = new byte[bufferSize];
            }

            public void Dispose()
            {
                Close();
            }

            public void Send(byte[] buf)
            {
                if (m_Handle == NTKernel.INVAILD_HANDLE)
                {
                    Connect();
                }

                //Build Message Head
                byte[] syncHead = BitConverter.GetBytes(SYNC_HEAD);
                byte[] length = BitConverter.GetBytes(buf.Length);
                byte[] lengthBuf = new byte[syncHead.Length + length.Length];
                
                syncHead.CopyTo(lengthBuf, 0);
                
                for (int i = syncHead.Length; i < lengthBuf.Length; i++)
                {
                    lengthBuf[i] = length[i - syncHead.Length];
                }

                WriteBuf(lengthBuf);

                //write content
                if (buf.Length < m_BufferSize)
                {
                    WriteBuf(buf);
                }
                else
                {
                    //the length of buf lardge than m_BufferSize

                    int offset = 0;

                    int len = Math.Min((int)m_BufferSize, buf.Length - offset);

                    byte[] sendbuf;

                    while (len > 0)
                    {
                        if (len == m_BufferSize)
                        {
                            sendbuf = m_SendBuf;
                        }
                        else
                        {
                            sendbuf = new byte[len];
                        }

                        System.IO.MemoryStream m = new System.IO.MemoryStream(sendbuf);
                        m.Write(buf, offset, len);
                        m.Close();
                        offset += len;
                        len = Math.Min((int)m_BufferSize, buf.Length - offset);
                        WriteBuf(sendbuf);
                    }
                }
            }

            ~PipeClient()
            {
                Dispose();
            }
        }
    }


    NTKernel.cs 
    这个程序文件Client 和 Server 都要,封装了相应的API函数

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;


    namespace Pipe.Win32
    {

        Data Structures

        public class NTKernel
        {
            public const uint PIPE_UNLIMITED_INSTANCES = 255;
            public const uint INVAILD_HANDLE = 0xFFFFFFFF;
            public const uint ERROR_FILE_NOT_FOUND = 2;
            public const uint ERROR_PIPE_BUSY = 231;

            internal const uint INFINITE = 0xFFFFFFFF;


            [DllImport("kernel32", EntryPoint = "GetLastError", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern uint GetLastError();

            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern uint CreateNamedPipe(string lpName, uint dwOpenMode,
               uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize,
               uint nDefaultTimeOut, SecurityAttributes lpSecurityAttributes);

            [DllImport("kernel32.dll")]
            public static extern bool ConnectNamedPipe(uint hNamedPipe,
               IntPtr lpOverlapped);

            [DllImport("kernel32.dll")]
            public static extern bool DisconnectNamedPipe(uint hNamedPipe);
            
            [DllImport("kernel32.dll", SetLastError=true)] 
            public static extern int WaitNamedPipeA (string lpNamedPipeName, int nTimeOut);

            [DllImport("kernel32.dll")]
            public static extern bool ReadFile(uint hFile, byte[] lpBuffer,
               uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

            [DllImport("kernel32.dll")]
            public static extern bool WriteFile(uint hFile, byte[] lpBuffer,
               uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
               IntPtr lpOverlapped);

            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern bool CloseHandle(uint hHandle);

            [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
            public static extern uint CreateFile(
                  string lpFileName,
                  uint dwDesiredAccess,
                  uint dwShareMode,
                  SecurityAttributes lpSecurityAttributes,
                  uint dwCreationDisposition,
                  uint dwFlagsAndAttributes,
                  int hTemplateFile
                  );

            Mutex


            Semaphore

            Event

        }

        class Mutex : IDisposable
        {
            IntPtr m_Handle;

            public Mutex(SecurityAttributes lpEventAttributes, bool bInitialOwner, string lpName)
            {
                m_Handle = NTKernel.CreateMutex(lpEventAttributes, bInitialOwner, lpName);

                if (m_Handle == IntPtr.Zero)
                {
                    uint err = NTKernel.GetLastError();
                    throw new Exception(String.Format("Create Event fail, error={0}",
                        err));
                }
            }

            public Mutex(bool bInitialOwner, string lpName)
            {
                m_Handle = NTKernel.CreateMutex(null, bInitialOwner, lpName);

                if (m_Handle == IntPtr.Zero)
                {
                    uint err = NTKernel.GetLastError();
                    throw new Exception(String.Format("Create Event fail, error={0}",
                        err));
                }
            }

            public bool WaitOne(uint dwMilliseconds)
            {
                WaitForState waitForState = (WaitForState)NTKernel.WaitForSingleObject((uint)m_Handle, dwMilliseconds);

                if (waitForState == WaitForState.WAIT_OBJECT_0)
                {
                    return true;
                }
                else if (waitForState == WaitForState.WAIT_TIMEOUT)
                {
                    return false;
                }
                else
                {
                    throw new System.Threading.AbandonedMutexException();
                }


            }

            public bool WaitOne()
            {
                return WaitOne(NTKernel.INFINITE);
            }

            public void ReleaseMutex()
            {
                NTKernel.ReleaseMutex(m_Handle);
            }

            public void Close()
            {
                lock (this)
                {
                    if (m_Handle != IntPtr.Zero)
                    {
                        if (NTKernel.CloseHandle((uint)m_Handle))
                        {
                            m_Handle = IntPtr.Zero;
                        }
                    }
                }
            }

            ~Mutex()
            {
                Dispose();
            }

            IDisposable Members

        }

        public class Event : IDisposable
        {
            IntPtr m_Handle;

            public Event()
            {
            }

            public Event(SecurityAttributes lpEventAttributes, bool bManualReset, bool bInitialState, string lpName)
            {
                m_Handle = NTKernel.CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName);

                if (m_Handle == IntPtr.Zero)
                {
                    uint err = NTKernel.GetLastError();
                    throw new Exception(String.Format("Create Event fail, error={0}",
                        err));
                }
            }

            public bool Open(EventAccess dwDesiredAccess, bool bInheritHandle, string lpName)
            {
                m_Handle = NTKernel.OpenEvent((uint)dwDesiredAccess, bInheritHandle, lpName);

                if (m_Handle == IntPtr.Zero)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }

            public WaitForState WaitFor(uint dwMilliseconds)
            {
                return (WaitForState)NTKernel.WaitForSingleObject((uint)m_Handle, dwMilliseconds);
            }

            public WaitForState WaitFor()
            {
                return WaitFor(NTKernel.INFINITE);
            }

            public void SetEvent()
            {
                NTKernel.SetEvent(m_Handle);
            }

            public void Release()
            {
                NTKernel.ResetEvent(m_Handle);
            }

            public void Close()
            {
                lock (this)
                {
                    if (m_Handle != IntPtr.Zero)
                    {
                        if (NTKernel.CloseHandle((uint)m_Handle))
                        {
                            m_Handle = IntPtr.Zero;
                        }
                    }
                }
            }

            ~Event()
            {
                Dispose();
            }

            IDisposable Members
        }
    }


    客户端调用

                byte[] buf = new byte[10240];
                Pipe.Client.PipeClient client = new Pipe.Client.PipeClient("test", 102400);

                for (int i = 0; i < 10000; i++)
                {
                    try
                    {
                        client.Send(buf);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    finally
                    {
                    }
                }


    服务器调用

            static bool begin = true;
            static System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            static int count = 0;
            static object lockObj = new object();

            static void ReceiveMessage(System.IO.MemoryStream m)
            {
                //Console.WriteLine(msg.Event);

                lock (lockObj)
                {

                    if (begin)
                    {
                        watch.Start();
                        begin = false;
                    }

                    count++;

                    if (count == 10000)
                    {
                        watch.Stop();
                        float len = m.Length;

                        Console.WriteLine(String.Format("{0} MB", (len * 10000 * 1000 / watch.ElapsedMilliseconds) / (1024 * 1024)));
                        Console.WriteLine(String.Format("{0} ms", watch.ElapsedMilliseconds));
                   
                    }
                }
            }

            static void ReceiveMessageError(Exception e)
            {
                Console.WriteLine(e.Message);
            }

            static void Main(string[] args)
            {
                Pipe.Server.PipeServer server = new Pipe.Server.PipeServer("Test", 102400);
                server.OnReceiveMessage = ReceiveMessage;
                server.OnReceiveMessageError = ReceiveMessageError;
                server.Listen();


            }


    源码下载位置

  • 相关阅读:
    HDU 4460 Friend Chains 第37届ACM/ICPC杭州赛区题目 (bfs求最短路,求两两之间最短路的最大值)
    HDU 4445 Crazy Tank (简单物理题,枚举)
    HDU 4433 locker 第37届ACM/ICPC 天津赛区现场赛C题(DP)
    JQuery 3级级联,3级联动,3级连动
    C++异常处理
    C++ Template
    学会用core dump调试程序错误(转)
    C++命名规则
    vim实用配置(转)
    GDB多进程调试(转)
  • 原文地址:https://www.cnblogs.com/xumaojun/p/8544099.html
Copyright © 2020-2023  润新知