C#实现的异步套接字,封装了server与client

最近半年以来都在从事suse10下的C++开发,开发工具也从豪门visual studio10降到了代码查看工具source insight。不过不得不说source insight阅读代码的效率绝对超过visual studio,虽然visual studio也能设置哪些功能,但真心没source insight顺手。不过悲剧的就是写代码的支持比文本好不了多少,调试的话,只能上传到suse10服务器上去然后慢慢的gdb调试了,最头大的就是那个makefile的编写,实在让人累。还是怀念windows下那种豪华的日子。

     废话不多说了,我写这篇文章不是为了诉苦的,只是为了继续写网络这边的。以前写过windows下的C++的网络编程的一些日子,虽然也被喷过不少,不过今天我还是要来写网络编程,只是语言更换为豪华的C#。之所以说C#豪华,相信同时使用C#与C++的人能体会到。

     frame work实在是太强大了,基本我就关注一点点东西就行了,很多类似工具的东西都是可以直接拿过来使用,而且最为关键的是我们在天朝,不用花钱用企业版,小小鄙视下自己,不过我还是会继续支持山寨盗版,谁让我是屌丝呢。

      今天文章中写的是异步,纯粹的异步,当然很多人看来很简单了,而且里面很多东西值得商榷,不过说真的,我真心感谢C#的线程池,不然我还要自己去写个threadpool。而且我没办法保证我写的没问题。

     直接上代码了,不讲思路了,没时间,最近太忙,已经几天没睡好了。

 

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace PPT.Comm
{
     ///   <summary>
    
///  接收数据流
    
///   </summary>
    
///   <param name="m_pSocket"> 异步套接字 </param>
    
///   <param name="m_pDatagram"> 接收到的数据流 </param>
     public  delegate  void AsyncDataAcceptedEventHandler(AsyncSocket m_pSocket,  byte[] m_pDatagram);

     ///   <summary>
    
///  发送完毕
    
///   </summary>
    
///   <param name="m_pSocket"> 异步套接字 </param>
    
///   <param name="m_pIsSuccess"> 发送结果 </param>
     public  delegate  void AsyncDataSendedEventHandler(AsyncSocket m_pSocket,  bool m_pIsSuccess);

     ///   <summary>
    
///  接收连接委托
    
///   </summary>
    
///   <param name="m_pSocket"> 异步套接字 </param>
     public  delegate  void AsyncSocketAcceptEventHandler(AsyncSocket m_pSocket);

     ///   <summary>
    
///  关闭连接委托
    
///   </summary>
    
///   <param name="m_pSocket"> 异步套接字 </param>
     public  delegate  void AsyncSocketClosedEventHandler(AsyncSocket m_pSocket);

     ///   <summary>
    
///  State object for receiving data from remote device.
    
///   </summary>
     class StateObject
    {
         //  Client socket.
         public Socket workSocket =  null;
         //  Size of receive buffer.
         public  const  int BufferSize =  1024 *  256;
         //  Receive buffer.
         public  byte[] buffer =  new  byte[BufferSize];
         //  Received data string.
         public StringBuilder sb =  new StringBuilder();
    }

     ///   <summary>
    
///  异步SOCKET
    
///   </summary>
     public  class AsyncSocket
    {
         #region 私有字段 成员

         private Socket m_socket =  null;                                              // socket
         string m_id =  "";                                                            // socket唯一标识,GUID

         private  readonly  bool m_isSerevr;                                            // 服务器标志位
         private  int m_iBackBag;
         private  string m_ipAddress;
         private  int m_port;

         private AsyncDataAcceptedEventHandler m_onAsyncDataAcceptedEvent =  null;     // 接收数据流
         private AsyncDataSendedEventHandler m_onAsyncDataSendedEvent =  null;         // 发送结束
         private AsyncSocketAcceptEventHandler m_onAsyncSocketAcceptEvent =  null;     // 接收连接
         private AsyncSocketClosedEventHandler m_onAsyncSocketClosedEvent =  null;     // 关闭连接
 
         #endregion

         #region 公共属性 成员

         ///   <summary>
        
///  获取SOCKET标志位
        
///   </summary>
         public  string ID 
        {
             get 
            { 
                 return m_id;
            } 
        }

         ///   <summary>
        
///  设置或获取机器标志位
        
///   </summary>
         public  string MachineKey 
        { 
             set
             get
        }

         ///   <summary>
        
///  获取、设置连接对象
        
///   </summary>
         public Socket LinkObject
        {
             get
            {
                 return m_socket;
            }
             set
            {
                m_socket = value;
            }
        }

         ///   <summary>
        
///  设置或获取线程退出标识
        
///   </summary>
         public  bool IsExit {  setget; }

         #endregion

         #region 公共事件 成员

         ///   <summary>
        
///  连接关闭事件
        
///   </summary>
         public  event AsyncSocketClosedEventHandler AsyncSocketClosedEvent
        {
            add
            {
                m_onAsyncSocketClosedEvent += value;
            }
            remove
            {
                m_onAsyncSocketClosedEvent -= value;
            }
        }

         ///   <summary>
        
///  连接接收事件
        
///   </summary>
         public  event AsyncSocketAcceptEventHandler AsyncSocketAcceptEvent
        {
            add
            {
                m_onAsyncSocketAcceptEvent += value;
            }
            remove
            {
                m_onAsyncSocketAcceptEvent -= value;
            }
        }

         ///   <summary>
        
///  数据接收完成事件
        
///   </summary>
         public  event AsyncDataAcceptedEventHandler AsyncDataAcceptedEvent
        {
            add
            {
                 this.m_onAsyncDataAcceptedEvent += value;
            }
            remove
            {
                 this.m_onAsyncDataAcceptedEvent -= value;
            }
        }

         ///   <summary>
        
///  数据发送完成事件
        
///   </summary>
         public  event AsyncDataSendedEventHandler AsyncDataSendedEvent
        {
            add
            {
                m_onAsyncDataSendedEvent += value;
            }
            remove
            {
                m_onAsyncDataSendedEvent -= value;
            }
        }

         #endregion

         #region 构造函数 成员

         ///   <summary>
        
///  构造函数
        
///   </summary>
        
///   <param name="m_pHostAddrss"> 主机地址,可为机器名或者IP </param>
        
///   <param name="m_pHostPort"> 主机端口 </param>
        
///   <param name="m_pIsAsServer"> 是否作为服务器,默认为false </param>
        
///   <param name="m_pICount"> 支持多少个客户端 </param>
         public AsyncSocket( string m_pHostAddrss,  int m_pHostPort,  bool m_pIsAsServer =  falseint m_pIBackBag =  10)
        {
            m_isSerevr = m_pIsAsServer;
            m_iBackBag = m_pIBackBag;
            m_ipAddress = m_pHostAddrss;
            m_port = m_pHostPort;
            m_id = Guid.NewGuid().ToString();
        }

         ///   <summary>
        
///  构造函数,用于服务器构造与客户端的异步socket
        
///   </summary>
        
///   <param name="LinkObject"> 客户端socket </param>
         private AsyncSocket(Socket linkObject)
        {
            m_socket = linkObject;
            m_id = Guid.NewGuid().ToString();
        }

         #endregion

         #region 公共方法

         ///   <summary>
        
///  打开通道
        
///   </summary>
         public  void AsyncOpen()
        {
             if (m_isSerevr)
            {
                IPAddress ip = Dns.GetHostAddresses(m_ipAddress)[ 0];
                IPEndPoint ipe =  new IPEndPoint(ip, m_port);
                m_socket =  new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_socket.Bind(ipe);
                m_socket.Listen(m_iBackBag);
                m_socket.BeginAccept( new AsyncCallback(AcceptCallBack),  null); // 异步
            }
             else
            {
                IPAddress ip = Dns.GetHostAddresses(m_ipAddress)[ 0];
                IPEndPoint ipe =  new IPEndPoint(ip, m_port);
                m_socket =  new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_socket.Connect(ipe);
            }
        }

         ///   <summary>
        
///  发送二进制数据
        
///   </summary>
        
///   <param name="SendData"></param>
         public  void AsyncSend( byte[] SendData)
        {
            m_socket.BeginSend(SendData,  0, SendData.Length,  0new AsyncCallback(SendCallBack), m_socket);
        }

         ///   <summary>
        
///  关闭通道
        
///   </summary>
         public  void AsyncClose()
        {
             if (!m_isSerevr)
            {
                m_socket.Shutdown(SocketShutdown.Both); // 关闭接收发送流
                m_socket.BeginDisconnect( false, CloseCallBack, m_socket); // 开始尝试断开
            }
             else 
            {
                m_socket.Shutdown(SocketShutdown.Both); // 关闭接收发送流
                Thread.Sleep( 200); // 等待现有任务处理完成
                m_socket.Dispose(); // 释放所有本地资源
            }
        }

         ///   <summary>
        
///  开始接受数据,连接建立之后,调用此方法
        
///   </summary>
         public  void BeginAcceptData()
        {
             // 开始接收数据
            StateObject state =  new StateObject();
            state.workSocket = m_socket;
            m_socket.BeginReceive(state.buffer,  0, StateObject.BufferSize,  0new AsyncCallback(ReceiveCallback), state);
        }

         #endregion

         #region 私有方法 成员

         #endregion

         #region 回调函数 成员

         ///   <summary>
        
///  接受客户端连接处理
        
///   </summary>
        
///   <param name="ar"></param>
         private  void AcceptCallBack(IAsyncResult ar)
        {
            Socket handler = m_socket.EndAccept(ar);
            AsyncSocket NewSocket =  new AsyncSocket(handler);

             // 激发事件,异步触发
             if (m_onAsyncSocketAcceptEvent !=  null)
                 foreach (AsyncSocketAcceptEventHandler item  in m_onAsyncSocketAcceptEvent.GetInvocationList())
                    item.BeginInvoke(NewSocket,  nullnull);

             // 继续投递监听请求
            m_socket.BeginAccept( new AsyncCallback(AcceptCallBack),  null);
        }

         ///   <summary>
        
///  接受字节流处理
        
///   </summary>
        
///   <param name="ar"></param>
         private  void ReceiveCallback(IAsyncResult ar)
        {
             try
            {
                StateObject state = ar.AsyncState  as StateObject;
                 // 读取数据
                 int bytesRead = m_socket.EndReceive(ar);
                 if (bytesRead >  0)
                {
                     byte[] _Readbyte =  new  byte[bytesRead];
                    Array.Copy(state.buffer,  0, _Readbyte,  0, bytesRead);
                     // 接收完成,激发事件
                     if (m_onAsyncDataAcceptedEvent !=  null)
                         foreach (AsyncDataAcceptedEventHandler item  in m_onAsyncDataAcceptedEvent.GetInvocationList())
                            item.BeginInvoke( this, _Readbyte,  nullnull);

                    state =  new StateObject(); // 继续投递接收委托
                    state.workSocket = m_socket;
                    m_socket.BeginReceive(state.buffer,  0, StateObject.BufferSize,  0new AsyncCallback(ReceiveCallback), state);
                }
            }
             catch (SocketException)
            {
                 if (m_onAsyncSocketClosedEvent !=  null)
                     foreach (AsyncSocketClosedEventHandler item  in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke( thisnullnull);
            }
        }

         ///   <summary>
        
///  发送结束处理
        
///   </summary>
        
///   <param name="ar"></param>
         private  void SendCallBack(IAsyncResult ar)
        {
             try
            {
                m_socket.EndSend(ar);
                 if (m_onAsyncDataSendedEvent !=  null)
                     foreach (AsyncDataSendedEventHandler item  in m_onAsyncDataSendedEvent.GetInvocationList())
                        item.BeginInvoke( thistruenullnull);
            }
             catch (SocketException)
            {
                 if (m_onAsyncDataSendedEvent !=  null)
                     foreach (AsyncDataSendedEventHandler item  in m_onAsyncDataSendedEvent.GetInvocationList())
                        item.BeginInvoke( thisfalsenullnull);

                 if (m_onAsyncSocketClosedEvent !=  null)
                     foreach (AsyncSocketClosedEventHandler item  in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke( thisnullnull);
            }
        }

         ///   <summary>
        
///  关闭后处理
        
///   </summary>
        
///   <param name="ar"></param>
         private  void CloseCallBack(IAsyncResult ar)
        {
             try
            {
                m_socket.EndDisconnect(ar);
                m_socket.Dispose();
                 if (m_onAsyncDataSendedEvent !=  null)
                     foreach (AsyncSocketClosedEventHandler item  in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke( thisnullnull);
            }
             catch (SocketException)
            {
                 if (m_onAsyncSocketClosedEvent !=  null)
                     foreach (AsyncSocketClosedEventHandler item  in m_onAsyncSocketClosedEvent.GetInvocationList())
                        item.BeginInvoke( thisnullnull);
            }  
        }

         #endregion
    }
}
复制代码

 

   代码注释还是蛮详细的,相信你看了也没什么不懂的地方。唯一让我不爽的是我异步事件不得不

                foreach (AsyncSocketAcceptEventHandler item in m_onAsyncSocketAcceptEvent.GetInvocationList())

                    item.BeginInvoke(NewSocket, null, null); 

这样的写法,很蛋疼。也试验了

Action asyncAction = () => m_onAsyncSocketAcceptEvent ();

asyncAction.BeginInvoke( null , null); 

 但郁闷的发现其实action虽然异步了,但那些事件还是顺序触发的,根本不是并发触发。无奈还是写那个蛋疼的foreach语句。顺便提到一句那个foreach中类型写全了,别用var,因为var会自动推断为Delegate。当然你自己再转换下也行,如果你喜欢的话。

 

我把代码贴出来的目的是找bug,还望各位大神多多指出其中问题。各种都可以,包括性能方面的。(我现在最怀疑的就是这里面到处异步,用线程池的资源会不会出现性能问题,毕竟线程有时候就是坑爹的) 

你可能感兴趣的:(server)