很久以来都是看别人的文章,吭哧赛吭哧歪,今天对自己的网络通讯支持类进行升级后,感觉是向社区回馈一些的时刻了。

这个 UdpSocket 是在以前的 BeginXXX/EndXXX基础上改进而来,目的是为了提供性能。为此参考了博客园、以及其它园的多篇

关于 .Net 2.0sp1 中新增的 xxxAsync 函数族的使用方法,在此一并致谢。

 别的不多说,请看下述代码。

首先是抄自 MSDN 中的 SocketAsyncEventArgsPool,用于实现初步的SocketAsyncEventArgs对象池:

 m_pool;
        private int _Capacity;                            // 池的最大容量


        
/// <summary>
        
/// 初始化对象池
        
/// </summary>
        
/// <param name="capacity">对象池中可以保持的最大对象SocketAsyncEventArgs的数量</param>
        public SocketAsyncEventArgsPool (int capacity)
        {
            _Capacity 
= capacity;
            m_pool 
= new Stack<SocketAsyncEventArgs>(capacity);
        }

        
/// <summary>
        
/// 将元素推入队列
        
/// 初始化时,还需将默认容量的预构建的元素加入池中
        
/// 注意:预构建的元素的 Completed 委托必须赋值
        
/// </summary>
        public void Push (SocketAsyncEventArgs item)
        {
            
if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); }
            
lock (m_pool) {
                m_pool.Push(item);
            }
        }

        
/// <summary>
        
/// 从池中获取一个SocketAsyncEventArgs实例
        
/// </summary>
        public SocketAsyncEventArgs Pop ( )
        {
            Debug.WriteLine(
string.Format("{0}, m_pool.Count={1}", DateTime.Now, m_pool.Count));
            
lock (m_pool) {
                
return m_pool.Pop( );
            }
        }

        
// The number of SocketAsyncEventArgs instances in the pool
        public int Count
        {
            
get { return m_pool.Count; }
        }

        
public int Capacity
        {
            
get { return _Capacity; }
        }

 

然后是核心的 UdpSocket 类实现

 

使用这个UdpSocket很简单,参考如下示例


    {
        private UdpSocket udp;
        
private int _Count;

        
public void Start ( )
        {
            udp 
= new UdpSocket( );
            udp.OnDataEventHandle 
= this;
            udp.CreateUdpSocket(
8405);
            udp.Start( );

        }

        
#region IDataEvent<UdpSocket> 成员

        
public int OnDataRecived (System.Net.EndPoint remoteHost, byte[] dataBuff, int dataSize)
        {

            System.Console.WriteLine(
"{0}\t{1}\t{2}\t{3}", DateTime.Now, remoteHost.ToString( ), dataSize, ASCIIEncoding.ASCII.GetString(dataBuff, 0, dataSize));

            
byte[] buff = ASCIIEncoding.ASCII.GetBytes(string.Format("{0},{1}", DateTime.Now, _Count++));

            udp.SendTo(
ref buff, buff.Length, remoteHost);

            
return ( dataSize );
        }

        
public int OnDataSended (System.Net.EndPoint remoteHost, byte[] dataBuff, int dataSize)
        {
            
return ( dataSize );
        }

        
#endregion

 

欢迎大家拍砖!

 

 

 参考文章:

 .NET3.5中的高性能 Socket API

 翻译:使用.net3.5的缓存池和SocketAsyncEventArgs类创建socket服务器

 

 关于 WinsockSockAddr 类的代码如下:

 WinsockSockAddr
    {
        const Int16 AF_INET = 2;
        
const Int16 AF_INET6 = 23;

        [StructLayout(LayoutKind.Sequential, Pack 
= 4)]
        
internal struct SOCKADDR_IN
        {
            
public Int16 _family;
            
public Int16 _port;
            
public Byte _addr0;
            
public Byte _addr1;
            
public Byte _addr2;
            
public Byte _addr3;
            
public Int32 _nothing;
        }

        
static readonly int SIZEOF_SOCKADDR_IN = Marshal.SizeOf(typeof(SOCKADDR_IN));

        [StructLayout(LayoutKind.Sequential)]
        
internal struct SOCKADDR_IN6
        {
            
public Int16 _family;
            
public Int16 _port;
            
public Int32 _flowInfo;
            
public Byte _addr0;
            
public Byte _addr1;
            
public Byte _addr2;
            
public Byte _addr3;
            
public Byte _addr4;
            
public Byte _addr5;
            
public Byte _addr6;
            
public Byte _addr7;
            
public Byte _addr8;
            
public Byte _addr9;
            
public Byte _addr10;
            
public Byte _addr11;
            
public Byte _addr12;
            
public Byte _addr13;
            
public Byte _addr14;
            
public Byte _addr15;
            
public Int32 _scopeID;
        }

        
static readonly int SIZEOF_SOCKADDR_IN6 = Marshal.SizeOf(typeof(SOCKADDR_IN6));

        
// Depending on the family type of address represented, either a SOCKADDR_IN
        
// or a SOCKADDR_IN6 will be referenced by _addr.  We'll pin the same object
        
// to _pinAddr, and finally keep a IntPtr to the alloc.
        object _addr;
        GCHandle _pinAddr;
        IntPtr _pAddr;

        
public WinsockSockAddr (IPEndPoint source)
            : 
this(source.Address, (short)source.Port)
        {
        }

        
public WinsockSockAddr (IPAddress source)
            : 
this(source, 0)
        {
        }

        
public WinsockSockAddr (IPAddress source, short port)
        {
            _pAddr 
= (IntPtr)0;

            
if (source.AddressFamily == AddressFamily.InterNetwork) {
                SOCKADDR_IN a;
                Byte[] addr 
= source.GetAddressBytes( );
                Debug.Assert(addr.Length 
== 4);

                a._family 
= AF_INET;
                a._port 
= IPAddress.HostToNetworkOrder(port);
                a._addr0 
= addr[0];
                a._addr1 
= addr[1];
                a._addr2 
= addr[2];
                a._addr3 
= addr[3];
                a._nothing 
= 0;

                _addr 
= a;
            } 
else if (source.AddressFamily == AddressFamily.InterNetworkV6) {
                SOCKADDR_IN6 a;
                Byte[] addr 
= source.GetAddressBytes( );
                Debug.Assert(addr.Length 
== 16);

                a._family 
= AF_INET6;
                a._port 
= IPAddress.HostToNetworkOrder(port);
                a._flowInfo 
= 0;
                a._addr0 
= addr[0];
                a._addr1 
= addr[1];
                a._addr2 
= addr[2];
                a._addr3 
= addr[3];
                a._addr4 
= addr[4];
                a._addr5 
= addr[5];
                a._addr6 
= addr[6];
                a._addr7 
= addr[7];
                a._addr8 
= addr[8];
                a._addr9 
= addr[9];
                a._addr10 
= addr[10];
                a._addr11 
= addr[11];
                a._addr12 
= addr[12];
                a._addr13 
= addr[13];
                a._addr14 
= addr[14];
                a._addr15 
= addr[15];
                a._scopeID 
= (Int32)source.ScopeId;

                _addr 
= a;
            } 
else {
                
throw new ArgumentException( );
            }

            _pinAddr 
= GCHandle.Alloc(_addr, GCHandleType.Pinned);
            _pAddr 
= _pinAddr.AddrOfPinnedObject( );
        }


        
void Close ( )
        {
            
if (_pinAddr.IsAllocated) {
                _pinAddr.Free( );
            }

            _addr 
= null;
            _pAddr 
= (IntPtr)0;
        }

        
~WinsockSockAddr ( )
        {
            Close( );
        }

        
public IntPtr PinnedSockAddr
        { 
get { return _pAddr; } }
    }

 


相关文章:

  • 2022-12-23
  • 2022-01-28
  • 2022-12-23
  • 2021-07-05
  • 2021-10-28
  • 2022-12-23
  • 2022-12-23
  • 2021-08-28
猜你喜欢
  • 2022-01-12
  • 2022-12-23
  • 2022-12-23
  • 2021-12-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案