您的位置:首页 > 其它

[原创]采用SocketAsyncEventArgs实现异步UDP收发

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

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

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

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

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

public sealed unsafe class 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; } }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: