采用管道进行通讯的例子

采用管道进行通讯的例子 作者:肖波     用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,                     0new SecurityAttributes(), (uint)CreateMode.OPEN_EXISTING, 00);                 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();         }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值