UDT 简介
参考 http://baike.baidu.com/view/1036563.htm
UDT C++源码
UDT c# 调用导出
// UDTLibary.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#ifndef WIN32
#include <cstdlib>
#include <cstring>
#include <netdb.h>
#include <signal.h>
#include <unistd.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
#include <algorithm>
#include <iostream>
#include "udt.h"
using namespace std;
struct RemoteEndPoint
{
public:
USHORT port;
char* ip;
};
extern "C" __declspec(dllexport)
int StartUp()
{
return UDT::startup();
};
extern "C" __declspec(dllexport)
int CleanUp()
{
return UDT::cleanup();
};
extern "C" __declspec(dllexport)
UDTSOCKET NewSocket(int family, int socktype, int protocol)
{
return UDT::socket(family,socktype,protocol);
}
extern "C" __declspec(dllexport)
int BindSocket(UDTSOCKET u,UDPSOCKET udpsockt)
{
return UDT::bind(u,udpsockt);
}
extern "C" __declspec(dllexport)
int Bind(UDTSOCKET usock,int family,int sockType,char*ip ,int port)
{
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = family;
hints.ai_socktype = sockType;
char service[16];
sprintf(service, "%d", port);
if (0 != getaddrinfo(ip, service, &hints, &res))
{
return -1;
}
if (UDT::ERROR == UDT::bind(usock, res->ai_addr, res->ai_addrlen))
{
return -1;
}
freeaddrinfo(res);
return 0;
}
extern "C" __declspec(dllexport)
int Listen(UDTSOCKET usock, int backlog)
{
return UDT::listen(usock,backlog);
}
extern "C" __declspec(dllexport)
UDTSOCKET Accept(UDTSOCKET usock,char* remoteip,int* iplen,int* port)
{
sockaddr_storage clientaddr;
int addrlen = sizeof(clientaddr);
UDTSOCKET sock= UDT::accept(usock, (sockaddr*)&clientaddr, &addrlen);
sockaddr_in* addr= (sockaddr_in*)&clientaddr;
*port=addr->sin_port;
char* ip=inet_ntoa(addr->sin_addr);
*iplen=strlen(ip);
memcpy(remoteip,ip,*iplen);
return sock;
}
extern "C" __declspec(dllexport)
int GetSockName(UDTSOCKET usock,char* remoteip,int* iplen,int* port)
{
struct sockaddr_in sa; ;
int namelen=sizeof(sa);
if(UDT::getsockname(usock,(struct sockaddr FAR *)&sa,&namelen)==0)
{
*port=sa.sin_port;
char* ip=inet_ntoa(sa.sin_addr);
*iplen=strlen(ip);
memcpy(remoteip,ip,*iplen);
return 0;
}
else
{
return -1;
}
};
extern "C" __declspec(dllexport)
int GetSockPeerName(UDTSOCKET usock,char* remoteip,int* iplen,int* port)
{
struct sockaddr_in sa; ;
int namelen=sizeof(sa);
if(UDT::getpeername(usock,(struct sockaddr FAR *)&sa,&namelen)==0)
{
*port=sa.sin_port;
char* ip=inet_ntoa(sa.sin_addr);
*iplen=strlen(ip);
memcpy(remoteip,ip,*iplen);
return 0;
}
else
{
return -1;
}
};
extern "C" __declspec(dllexport)
int Connect(UDTSOCKET usock,int family,int sockType,char* ip,int port)
{
addrinfo hints;
addrinfo* res;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = family;
hints.ai_socktype = sockType;
char service[16];
sprintf(service, "%d", port);
if (0 != getaddrinfo(ip, service, &hints, &res))
{
return -1;
}
if (UDT::ERROR == UDT::connect(usock, res->ai_addr, res->ai_addrlen))
{
return -1;
}
freeaddrinfo(res);
return 0;
};
extern "C" __declspec(dllexport)
int Close(UDTSOCKET usock)
{
return UDT::close(usock);
}
extern "C" __declspec(dllexport)
int Send(UDTSOCKET usock , char* buffer,int len)
{
int offset=0;
int sendLen=0;
SendRetry:
sendLen= UDT::send(usock,&buffer[offset],len-offset,0);
if(sendLen<0) return sendLen;
offset+=sendLen;
if(offset<len)
{
goto SendRetry;
}
else if(offset>len)
{
return -1;
}
return offset;
};
extern "C" __declspec(dllexport)
int Receive(UDTSOCKET usock , char* buffer,int len)
{
return UDT::recv(usock,buffer,len,0);
};
extern "C" __declspec(dllexport)
int Perfmon(UDTSOCKET u, CPerfMon* perf, bool clear)
{
return UDT::perfmon(u, perf, clear);
}
extern "C" __declspec(dllexport)
int GetSocketOption(UDTSOCKET u, int level, UDT::SOCKOPT optname, void* optval, int* optlen)
{
return UDT::getsockopt(u, level, optname, optval, optlen);
}
extern "C" __declspec(dllexport)
int SetSocketOption(UDTSOCKET u, int level, UDT::SOCKOPT optname, const void* optval, int optlen)
{
return UDT::setsockopt(u, level, optname, optval, optlen);
}
extern "C" __declspec(dllexport)
UDTSTATUS GetSocketState(UDTSOCKET u)
{
return UDT::getsockstate(u);
}
extern "C" __declspec(dllexport)
int64_t SendFile(UDTSOCKET u, fstream& ifs, int64_t& offset, int64_t size, int block)
{
return UDT::sendfile(u,ifs,offset,size,block);
}
extern "C" __declspec(dllexport)
int64_t RecvFile(UDTSOCKET u, fstream& ofs, int64_t& offset, int64_t size, int block)
{
return UDT::recvfile(u, ofs, offset, size, block);
}
extern "C" __declspec(dllexport)
int GetErrorCode()
{
return UDT::getlasterror().getErrorCode();
}
extern "C" __declspec(dllexport)
void GetErrorMessage(char* str,int len, int* errLen,int* errorCode)
{
CUDTException err=UDT::getlasterror();
*errorCode=err.getErrorCode();
const char* errMsg= err.getErrorMessage();
int msgLen=strlen(errMsg);
if(msgLen<= len)
{
memcpy(str,errMsg,msgLen);
}
else
{
memcpy(str,errMsg, len);
}
*errLen=msgLen;
}
extern "C" __declspec(dllexport)
int Select(int nfds,UDTSOCKET* read,int*readlen,UDTSOCKET*write,int*writelen,UDTSOCKET*except,int*exceptlen,const struct timeval* timeout)
{
UDT::UDSET readfds;
UDTSOCKET* tempRead=read;
for(int i=0;i<*readlen;i++)
{
readfds.insert(*tempRead++ );
}
UDT::UDSET writefds;
UDTSOCKET* tempWrite=write;
for(int i=0;i<*writelen;i++)
{
writefds.insert(*tempWrite++);
}
UDT::UDSET exceptfds;
UDTSOCKET* tempExcept=except;
for(int i=0;i<*exceptlen;i++)
{
exceptfds.insert(*tempExcept++);
}
int result=UDT::select(nfds,&readfds,&writefds,&exceptfds,timeout);
*readlen=readfds.size();
*writelen=writefds.size();
*exceptlen=exceptfds.size();
set<UDTSOCKET>::reverse_iterator readrit;
for(readrit=readfds.rbegin();readrit!=readfds.rend();readrit++)
{
*read++=*readrit;
}
set<UDTSOCKET>::reverse_iterator writerit;
for(writerit=writefds.rbegin();writerit!=writefds.rend();writerit++)
{
*write++=*writerit;
}
set<UDTSOCKET>::reverse_iterator exceptrit;
for(exceptrit=exceptfds.rbegin();exceptrit!=exceptfds.rend();exceptrit++)
{
*except++=*exceptrit;
}
return result;
}
C#封装方法
CPerfMon.cs
public struct CPerfMon
{
// global measurements
public long msTimeStamp; // time since the UDT entity is started, in milliseconds
public long pktSentTotal; // total number of sent data packets, including retransmissions
public long pktRecvTotal; // total number of received packets
public int pktSndLossTotal; // total number of lost packets (sender side)
public int pktRcvLossTotal; // total number of lost packets (receiver side)
public int pktRetransTotal; // total number of retransmitted packets
public int pktSentACKTotal; // total number of sent ACK packets
public int pktRecvACKTotal; // total number of received ACK packets
public int pktSentNAKTotal; // total number of sent NAK packets
public int pktRecvNAKTotal; // total number of received NAK packets
public long usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive)
// local measurements
public long pktSent; // number of sent data packets, including retransmissions
public long pktRecv; // number of received packets
public int pktSndLoss; // number of lost packets (sender side)
public int pktRcvLoss; // number of lost packets (receiver side)
public int pktRetrans; // number of retransmitted packets
public int pktSentACK; // number of sent ACK packets
public int pktRecvACK; // number of received ACK packets
public int pktSentNAK; // number of sent NAK packets
public int pktRecvNAK; // number of received NAK packets
public double mbpsSendRate; // sending rate in Mb/s
public double mbpsRecvRate; // receiving rate in Mb/s
public long usSndDuration; // busy sending time (i.e., idle time exclusive)
// instant measurements
public double usPktSndPeriod; // packet sending period, in microseconds
public int pktFlowWindow; // flow window size, in number of packets
public int pktCongestionWindow; // congestion window size, in number of packets
public int pktFlightSize; // number of packets on flight
public double msRTT; // RTT, in milliseconds
public double mbpsBandwidth; // estimated bandwidth, in Mb/s
public int byteAvailSndBuf; // available UDT sender buffer size
public int byteAvailRcvBuf; // available UDT receiver buffer size
}
SOCKOPT.cs
public enum SOCKOPT
{
/// <summary>
/// 最大传输单位
/// </summary>
UDT_MSS,
/// <summary>
/// 是否阻塞发送
/// </summary>
UDT_SNDSYN,
/// <summary>
/// 是否阻塞接收
/// </summary>
UDT_RCVSYN,
/// <summary>
/// 自定义拥塞控制算法
/// </summary>
UDT_CC,
/// <summary>
/// 窗口大小
/// </summary>
UDT_FC,
/// <summary>
/// 发送队列缓冲最大值
/// </summary>
UDT_SNDBUF,
/// <summary>
/// UDT接收缓冲大小
/// </summary>
UDT_RCVBUF,
/// <summary>
/// 关闭时等待数据发送完成
/// </summary>
UDT_LINGER,
/// <summary>
/// UDP发送缓冲大小
/// </summary>
UDP_SNDBUF,
/// <summary>
/// UDP接收缓冲大小
/// </summary>
UDP_RCVBUF,
/// <summary>
/// maximum datagram message size
/// </summary>
UDT_MAXMSG,
/// <summary>
/// time-to-live of a datagram message
/// </summary>
UDT_MSGTTL,
/// <summary>
/// 会合连接模式
/// </summary>
UDT_RENDEZVOUS,
/// <summary>
/// send()超时
/// </summary>
UDT_SNDTIMEO,
/// <summary>
/// recv()超时
/// </summary>
UDT_RCVTIMEO,
/// <summary>
/// 复用一个已存在的端口或者创建一个新的端口
/// </summary>
UDT_REUSEADDR,
/// <summary>
/// 当前连接可以使用的最大带宽(bytes per second)
/// </summary>
UDT_MAXBW,
/// <summary>
/// current socket state, see UDTSTATUS, read only
/// </summary>
UDT_STATE,
/// <summary>
/// current avalable events associated with the socket
/// </summary>
UDT_EVENT
};
UDTSTATUS.cs
public enum UDTSTATUS
{
INIT = 1,
OPENED,
LISTENING,
CONNECTING,
CONNECTED,
BROKEN,
CLOSING,
CLOSED,
NONEXIST
}
UDTException.cs
public class UDTException : Exception
{
public int ErrorCode { get; private set; }
public UDTException(string message, int errorCode)
: base(message)
{
this.ErrorCode = errorCode;
}
public UDTException(int errorCode)
{
this.ErrorCode = errorCode;
}
public override string ToString()
{
return string.Format("ErrorCode={0},Exception:{0}", base.ToString());
}
}
NativeUDT.cs
internal static class NativeUDT
{
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int StartUp();
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int CleanUp();
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr NewSocket(AddressFamily family, SocketType socktype, ProtocolType protocol);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int BindSocket(IntPtr udtSocket, IntPtr udpsockHandle);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int BindSocket(IntPtr udtSocket, Socket udpsockHandle);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Bind(IntPtr udtSocket, AddressFamily family, SocketType sockType, string ip, int port);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Listen(IntPtr udtSocket, int backlog);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern IntPtr Accept(IntPtr udtSocket, byte* ip, ref int iplen, ref int port);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int GetSockName(IntPtr usock, byte* remoteip, ref int iplen, ref int port);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int GetSockPeerName(IntPtr usock, byte* remoteip, ref int iplen, ref int port);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Connect(IntPtr udtSocket, AddressFamily family, SocketType sockType, string ip, int port);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Close(IntPtr udtSocket);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int GetSocketOption(IntPtr udtSocket, int level, SOCKOPT optname, IntPtr optval, ref int optlen);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int SetSocketOption(IntPtr udtSocket, int level, SOCKOPT optname, IntPtr optval, int optlen);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int SetSocketOption(IntPtr udtSocket, int level, SOCKOPT optname, ref int optval, int optlen);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int SetSocketOption(IntPtr udtSocket, int level, SOCKOPT optname, ref bool optval, int optlen);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Send(IntPtr udtSocket, IntPtr buf, int len);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int Send(IntPtr udtSocket, byte* buf, int len);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Receive(IntPtr udtSocket, IntPtr buf, int len);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int Receive(IntPtr udtSocket, byte* buf, int len);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int Perfmon(IntPtr udtSocket, ref CPerfMon perf, bool clear);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern UDTSTATUS GetSocketState(IntPtr udtSocket);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int GetErrorCode();
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void GetErrorMessage(StringBuilder errorMsg, int len, ref int errorlen, ref int errorCode);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, SetLastError = true), SuppressUnmanagedCodeSecurity()]
public static extern int Select([In]int nfds, [In, Out]IntPtr[] readfds, ref int readLen, [In, Out]IntPtr[] writefds, ref int writeLen, [In, Out]IntPtr[] exceptfds, ref int exceptLen, [In]IntPtr timeoutMicroseconds);
[DllImport("UDTLibary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, SetLastError = true), SuppressUnmanagedCodeSecurity()]
public static extern int Select([In]int nfds, [In, Out]IntPtr[] readfds, ref int readLen, [In, Out]IntPtr[] writefds, ref int writeLen, [In, Out]IntPtr[] exceptfds, ref int exceptLen, [In]ref TimeValue timeoutMicroseconds);
}
TimeValue.cs
[StructLayout(LayoutKind.Sequential)]
internal struct TimeValue
{
public int Seconds;
public int Microseconds;
}
UDTSocket.cs
/// <summary>
/// UDTSocket
/// </summary>
/// <example>
/// <![CDATA[
/// private UDTSocket CreateSocket(string ip = "0.0.0.0", int port = 0, bool rendezvous = false)
/// {
/// UDTSocket sock = new UDTSocket();
/// int snd_buf = 64000;
/// int rcv_buf = 64000;
/// sock.SetSocketOption(SOCKOPT.UDT_SNDBUF, snd_buf);
/// sock.SetSocketOption(SOCKOPT.UDT_RCVBUF, rcv_buf);
/// sock.SetSocketOption(SOCKOPT.UDP_SNDBUF, snd_buf);
/// sock.SetSocketOption(SOCKOPT.UDP_RCVBUF, rcv_buf);
/// int fc = 64;
/// sock.SetSocketOption(SOCKOPT.UDT_FC, fc);
/// bool reuse = true;
/// sock.SetSocketOption(SOCKOPT.UDT_REUSEADDR, reuse);
/// sock.SetSocketOption(SOCKOPT.UDT_RENDEZVOUS, rendezvous);
/// sock.SetSocketOption(SOCKOPT.UDT_MSS, (int)this.numMTU.Value);
/// sock.SetSocketOption(SOCKOPT.UDT_SNDSYN, this.ckSendSyn.Checked);
/// sock.SetSocketOption(SOCKOPT.UDT_RCVSYN, this.ckReviceSyn.Checked);
/// sock.Bind("0.0.0.0", port);
/// return sock;
/// }
/// ]]>
/// </example>
/// <remarks>绑定现有Socket时使用void Bind(Socket socket)方法。</remarks>
public sealed class UDTSocket : Collect
{
private static readonly TracingImpl Tracing = TracingManager.GetTracing(typeof(UDTSocket));
/// <summary>
/// 获取UDT本地监听地址
/// </summary>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
unsafe public IPEndPoint LocalEndPoint
{
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int port = 0;
byte[] ip = new byte[15];
fixed (byte* ptr = ip)
{
int iplen = 0;
if (NativeUDT.GetSockName(this.Handle, ptr, ref iplen, ref port) != 0)
{
return null;
}
else
{
return new IPEndPoint(IPAddress.Parse(Encoding.Default.GetString(ip, 0, iplen)), port);
}
}
}
}
/// <summary>
/// 获取UDT远程地址
/// </summary>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
unsafe public IPEndPoint RmoteEndPoint
{
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int port = 0;
byte[] ip = new byte[15];
fixed (byte* ptr = ip)
{
int iplen = 0;
if (NativeUDT.GetSockPeerName(this.Handle, ptr, ref iplen, ref port) != 0)
{
return null;
}
else
{
return new IPEndPoint(IPAddress.Parse(Encoding.Default.GetString(ip, 0, iplen)), port);
}
}
}
}
/// <summary>
/// 当前UDT句柄
/// </summary>
public IntPtr Handle
{
get;
private set;
}
static UDTSocket()
{
NativeUDT.StartUp();
//AppDomain.CurrentDomain.ProcessExit += delegate
//{
// NativeUDT.CleanUp();
//};
}
~UDTSocket()
{
this.Dispose();
}
public AddressFamily Family { get; private set; }
public SocketType SocketType { get; private set; }
public UDTSocket()
: this(AddressFamily.InterNetwork, SocketType.Stream)
{
}
/// <summary>
///
/// </summary>
/// <param name="family"></param>
/// <param name="sockType"></param>
/// <remarks>SocketType目前只实现了Stream形式</remarks>
public UDTSocket(AddressFamily family, SocketType sockType)
{
// SOCK_STREAM: 提供面向连接的稳定数据传输,即TCP协议。
// SOCK_DGRAM: 使用不连续不可靠的数据包连接。
// SOCK_PACKET: 与网络驱动程序直接通信。
// 注:此处的SOCK_STREAM并不是表示UDT将会使用TCP类型的Socket,在底层将会转化为UDT_STREAM
// 并且在UDT中仅支持SOCK_STREAM和SOCK_DGRAM,分别对应UDT_STREAM和UDT_DGRAM
// 此处实际上最终调用了CUDTUnited的newSocket,第一个参数会被直接设置到CUDT的m_iIPversion,第二个参数会被映射为UDT的连接类型,第三个参数被忽略,没有实际意义
this.Handle = NativeUDT.NewSocket(family, sockType, (ProtocolType)0);
if (this.Handle == IntPtr.Zero)
{
throw GetUDTException();
}
this.Family = family;
this.SocketType = sockType;
}
/// <summary>
/// 获取当前UDT状态
/// </summary>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public UDTSTATUS State
{
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
return NativeUDT.GetSocketState(this.Handle);
}
}
/// <summary>
/// 获取UDT性能相关数据
/// </summary>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public CPerfMon Perfmon
{
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
CPerfMon perfmon = new CPerfMon();
NativeUDT.Perfmon(this.Handle, ref perfmon, false);
return perfmon;
}
}
/// <summary>
/// 最大传输带宽
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int MaxBandWith
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_MAXBW, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_MAXBW, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// UDT发送缓冲区队列大小
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int UDTSendBufferSize
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 1) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDT_SNDBUF, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_SNDBUF, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// UDT接收缓冲区队列大小
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int UDTReviceBufferSize
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 0) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDT_RCVBUF, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_RCVBUF, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// UDP发送缓冲区队列大小
/// </summary>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int UDPSendBufferSize
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 0) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDP_SNDBUF, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDP_SNDBUF, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// UDP接收缓冲区队列大小
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int UDPReviceBufferSize
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 0) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDP_RCVBUF, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDP_RCVBUF, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 窗口大小
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int WindowSize
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 0) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDT_FC, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_FC, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 最大传输单元
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ArgumentException">vlaue must be >=1</exception>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int MSS
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (value < 0) throw new ArgumentException();
this.SetSocketOption(SOCKOPT.UDT_MSS, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_MSS, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 发送超时时间
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int SendTimeOut
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_SNDTIMEO, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_SNDTIMEO, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 接收超时时间
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public int ReviceTimeOut
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_RCVTIMEO, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(4);
try
{
this.GetSocketOption(SOCKOPT.UDT_RCVTIMEO, ptr, 4);
return Marshal.ReadInt32(ptr);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 是否汇合连接模式
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public bool IsRendezvous
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_RENDEZVOUS, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(1);
try
{
this.GetSocketOption(SOCKOPT.UDT_RENDEZVOUS, ptr, 1);
return Convert.ToBoolean(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 复用一个已存在的端口或者创建一个新的端口
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public bool IsReuseAddress
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_REUSEADDR, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(1);
try
{
this.GetSocketOption(SOCKOPT.UDT_REUSEADDR, ptr, 1);
return Convert.ToBoolean(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 设置关闭时是否等待数据发送完成
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public bool IsClosedLinger
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_LINGER, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(1);
try
{
this.GetSocketOption(SOCKOPT.UDT_REUSEADDR, ptr, 1);
return Convert.ToBoolean(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 是否同步接收
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public bool IsReviceSyn
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_RCVSYN, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(1);
try
{
this.GetSocketOption(SOCKOPT.UDT_RCVSYN, ptr, 1);
return Convert.ToBoolean(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
/// <summary>
/// 是否同步发送
/// </summary>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public bool IsSendSyn
{
set
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.SetSocketOption(SOCKOPT.UDT_RCVSYN, value);
}
get
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
IntPtr ptr = Marshal.AllocHGlobal(1);
try
{
this.GetSocketOption(SOCKOPT.UDT_SNDSYN, ptr, 1);
return Convert.ToBoolean(Marshal.ReadByte(ptr));
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
}
private UDTSocket(IntPtr handle)
{
this.Handle = handle;
}
/// <summary>
/// 绑定本机地址
/// </summary>
/// <param name="ip">本机IP</param>
/// <param name="port">监听端口</param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void Bind(string ip, int port)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (NativeUDT.Bind(this.Handle, this.Family, this.SocketType, ip, port) != 0)
{
throw GetUDTException();
}
}
private Socket bindSocket = null;
/// <summary>
/// 绑定现有Socket
/// </summary>
/// <param name="socket">现有Socket</param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void Bind(Socket socket)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
this.Bind(socket.Handle);
bindSocket = socket;
}
/// <summary>
/// 绑定现有Socket
/// </summary>
/// <param name="socket">现有Socket句柄</param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void Bind(IntPtr udpHandle)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (udpHandle == IntPtr.Zero)
{
throw new ArgumentException("udpHandle");
}
if (NativeUDT.BindSocket(this.Handle, udpHandle) != 0)
{
throw GetUDTException();
}
}
/// <summary>
/// 启动监听
/// </summary>
/// <param name="backlog">挂起连接队列的最大长度</param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void Listen(int backlog)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (NativeUDT.Listen(this.Handle, backlog) != 0)
{
throw GetUDTException();
}
}
/// <summary>
/// 建立与远程主机的连接
/// </summary>
/// <param name="ip">远程主机的名称</param>
/// <param name="port">远程主机的端口号</param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void Connect(string ip, int port)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
if (NativeUDT.Connect(this.Handle, this.Family, this.SocketType, ip, port) != 0)
{
throw GetUDTException();
}
}
public IAsyncResult BeginConnect(string ip, int port, AsyncCallback asyncCallback, object state = null)
{
ConnectHandle func = new ConnectHandle(this.Connect);
AsyncCallback callbackDelegate = asyncCallback;
if (asyncCallback != null)
{
AsyncCallbackDelegate tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = func };
callbackDelegate = tmp.AsyncCallBack;
}
var asyncResult = func.BeginInvoke(ip, port, callbackDelegate, state);
return new AsyncResultDelegate(asyncResult) { Delegate = func };
}
public void EndConnect(IAsyncResult ra)
{
AsyncResultDelegate asyncResultDelegate = (AsyncResultDelegate)ra;
ConnectHandle fun = (ConnectHandle)asyncResultDelegate.Delegate;
fun.EndInvoke(asyncResultDelegate.AsyncResult);
}
/// <summary>
/// 为新建连接创建新的UDTSocket
/// </summary>
/// <param name="remote">请求连接的远程地址</param>
/// <returns>连接的客户端</returns>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
unsafe public UDTSocket Accept(out IPEndPoint remote)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int port = 0;
byte[] ip = new byte[15];
fixed (byte* ptr = ip)
{
int iplen = 0;
IntPtr acceptHandle = NativeUDT.Accept(this.Handle, ptr, ref iplen, ref port);
if (acceptHandle == IntPtr.Zero)
{
throw GetUDTException();
}
else
{
remote = new IPEndPoint(IPAddress.Parse(Encoding.Default.GetString(ip, 0, iplen)), port);
UDTSocket sock = new UDTSocket(acceptHandle);
sock.Family = this.Family;
sock.SocketType = this.SocketType;
return sock;
}
}
}
public IAsyncResult BeginAccept(AsyncCallback asyncCallback, object state = null)
{
IPEndPoint remote = null;
AcceptHandle<UDTSocket> func = new AcceptHandle<UDTSocket>(this.Accept);
AsyncCallback callbackDelegate = asyncCallback;
if (asyncCallback != null)
{
AsyncCallbackDelegate tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = func };
callbackDelegate = tmp.AsyncCallBack;
}
var asyncResult = func.BeginInvoke(out remote, callbackDelegate, state);
return new AsyncResultDelegate(asyncResult) { Delegate = func };
}
public UDTSocket EndAccept(IAsyncResult ra, out IPEndPoint remote)
{
AsyncResultDelegate asyncResultDelegate = (AsyncResultDelegate)ra;
AcceptHandle<UDTSocket> fun = (AcceptHandle<UDTSocket>)asyncResultDelegate.Delegate;
return fun.EndInvoke(out remote, asyncResultDelegate.AsyncResult);
}
public IAsyncResult BeginClose(AsyncCallback asyncCallback, object state = null)
{
Action func = new Action(this.Close);
AsyncCallback callbackDelegate = asyncCallback;
if (asyncCallback != null)
{
AsyncCallbackDelegate tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = func };
callbackDelegate = tmp.AsyncCallBack;
}
var asyncResult = func.BeginInvoke(callbackDelegate, state);
return new AsyncResultDelegate(asyncResult) { Delegate = func };
}
public void EndClose(IAsyncResult ra)
{
AsyncResultDelegate asyncResultDelegate = (AsyncResultDelegate)ra;
Action fun = (Action)asyncResultDelegate.Delegate;
fun.EndInvoke(asyncResultDelegate.AsyncResult);
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
this.Dispose();
}
/// <summary>
/// 发送数据
/// </summary>
/// <param name="buffer">发送缓冲区</param>
/// <param name="offset">发送起始索引</param>
/// <param name="len">需要发送的数据长度</param>
/// <returns>发送的数据大小</returns>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
/// <remarks>数据长度0不代表发送失败,只说明发送的数据量为0</remarks>
[MethodImpl(MethodImplOptions.Synchronized)]
unsafe public int Send(byte[] buffer, int offset, int len)
{
#if UsingIntPtr
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(buffer, offset, ptr, len);
int sendLen = NativeUDT.Send(this.Handle, ptr, len);
Marshal.FreeHGlobal(ptr);
if (sendLen < 0) throw GetUDTException();
return sendLen;
#else
if (!this.IsSendSyn)
{
List<UDTSocket> writefds = new List<UDTSocket>();
while (!this.IsDisposed && writefds.Count == 0)
{
writefds.Add(this);
UDTSocket.Select(null, writefds, null, 1000);
}
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
}
fixed (byte* ptr = &buffer[offset])
{
int sendlen = NativeUDT.Send(this.Handle, ptr, len);
if (sendlen < 0)
{
throw GetUDTException();
}
return sendlen;
}
#endif
}
/// <summary>
/// 异步发送数据
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <param name="asyncCallback"></param>
/// <param name="state"></param>
/// <returns></returns>
/// <remarks>异步发送不保证数据发送的顺序</remarks>
public IAsyncResult BeginSend(byte[] buffer, int offset, int len, AsyncCallback asyncCallback, object state = null)
{
TransferHandle func = new TransferHandle(this.Send);
AsyncCallback callbackDelegate = asyncCallback;
if (asyncCallback != null)
{
AsyncCallbackDelegate tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = func };
callbackDelegate = tmp.AsyncCallBack;
}
byte[] data = new byte[len];
Array.Copy(buffer, offset, data, 0, len);
var asyncResult = func.BeginInvoke(data, 0, len, callbackDelegate, state);
return new AsyncResultDelegate(asyncResult) { Delegate = func };
}
public int EndSend(IAsyncResult ra)
{
AsyncResultDelegate asyncResultDelegate = (AsyncResultDelegate)ra;
TransferHandle fun = (TransferHandle)asyncResultDelegate.Delegate;
int len = fun.EndInvoke(asyncResultDelegate.AsyncResult);
return len;
}
/// <summary>
/// 接收数据
/// </summary>
/// <param name="buffer">接收缓冲区</param>
/// <param name="offset">接收缓冲区起始索引</param>
/// <param name="len">最大接收长度</param>
/// <returns>接收的数据大小</returns>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
/// <remarks>接收数据长度0不代表客户端关闭,只说明接收的数据量为0</remarks>
unsafe public int Receive(byte[] buffer, int offset, int len)
{
#if UsingIntPtr
IntPtr ptr = Marshal.AllocHGlobal(len);
int reviceLen = NativeUDT.Receive(this.Handle, ptr, len);
if (reviceLen > 0)
{
Marshal.Copy(ptr, buffer, offset, reviceLen);
}
Marshal.FreeHGlobal(ptr);
if (reviceLen < 0) throw GetUDTException();
return reviceLen;
#else
if (!this.IsReviceSyn && !this.IsDisposed)
{
List<UDTSocket> readfds = new List<UDTSocket>();
readfds.Add(this);
UDTSocket.Select(readfds, null, null, 1000);
if (readfds.Count == 0)
{
return 0;
}
}
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
fixed (byte* ptr = &buffer[offset])
{
int reviceLen = NativeUDT.Receive(this.Handle, ptr, len);
if (reviceLen < 0 && NativeUDT.GetErrorCode() != 0)
{
GetUDTException();
}
return reviceLen;
}
#endif
}
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public IAsyncResult BeginReceive(byte[] buffer, int offset, int len, AsyncCallback asyncCallback, object state = null)
{
TransferHandle func = new TransferHandle(this.Receive);
AsyncCallback callBack = asyncCallback;
if (asyncCallback != null)
{
AsyncCallbackDelegate tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = func };
callBack = tmp.AsyncCallBack;
}
var asyncResult = func.BeginInvoke(buffer, offset, len, callBack, state);
return new AsyncResultDelegate(asyncResult) { Delegate = func };
}
public int EndReceive(IAsyncResult ra)
{
AsyncResultDelegate asyncResultDelegate = (AsyncResultDelegate)ra;
TransferHandle fun = (TransferHandle)asyncResultDelegate.Delegate;
int len = fun.EndInvoke(asyncResultDelegate.AsyncResult);
return len;
}
/// <summary>
/// 设置UDT相关属性
/// </summary>
/// <param name="optname"></param>
/// <param name="value"></param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void SetSocketOption(SOCKOPT optname, int value)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int result = NativeUDT.SetSocketOption(this.Handle, 0, optname, ref value, sizeof(int));
if (result != 0)
{
throw GetUDTException();
}
}
/// <summary>
/// 设置UDT相关属性
/// </summary>
/// <param name="optname"></param>
/// <param name="value"></param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void SetSocketOption(SOCKOPT optname, bool value)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int result = NativeUDT.SetSocketOption(this.Handle, 0, optname, ref value, sizeof(bool));
if (result != 0)
{
throw GetUDTException();
}
}
/// <summary>
/// 获取UDT相关属性
/// </summary>
/// <param name="optname"></param>
/// <param name="ptr"></param>
/// <param name="len"></param>
/// <exception cref="UDTException"/>
/// <exception cref="ObjectDisposedException">UDT被释放时引发</exception>
public void GetSocketOption(SOCKOPT optname, IntPtr ptr, int len)
{
if (this.IsDisposed) throw new ObjectDisposedException("UDTSocket");
int result = NativeUDT.GetSocketOption(this.Handle, 0, optname, ptr, ref len);
if (result != 0)
{
throw GetUDTException();
}
}
private static UDTException GetUDTException()
{
int len = 2048;
StringBuilder sb = new StringBuilder(len);
int errorCode = 0;
int errorLen = 0;
NativeUDT.GetErrorMessage(sb, len, ref errorLen, ref errorCode);
return new UDTException(sb.ToString().Substring(0, errorLen), errorCode);
}
private static void MicrosecondsToTimeValue(long microSeconds, ref TimeValue socketTime)
{
socketTime.Seconds = (int)(microSeconds / 0xf4240L);
socketTime.Microseconds = (int)(microSeconds % 0xf4240L);
}
public static int Select(IList<UDTSocket> checkRead, IList<UDTSocket> checkWrite, IList<UDTSocket> checkError, int microSeconds)
{
if ((((checkRead == null) || (checkRead.Count == 0)) && ((checkWrite == null) || (checkWrite.Count == 0))) && ((checkError == null) || (checkError.Count == 0)))
{
throw new ArgumentNullException("checkRead or checkWrite or checkError must be one is not null.");
}
IntPtr[] readfds = SocketListToFileDescriptorSet(checkRead);
IntPtr[] writefds = SocketListToFileDescriptorSet(checkWrite);
IntPtr[] exceptfds = SocketListToFileDescriptorSet(checkError);
int readlen = readfds == null ? 0 : readfds.Length;
int writelen = writefds == null ? 0 : writefds.Length;
int exceptlen = exceptfds == null ? 0 : exceptfds.Length;
int result = 0;
if (microSeconds != -1)
{
TimeValue socketTime = new TimeValue();
MicrosecondsToTimeValue((long)((ulong)microSeconds), ref socketTime);
result = NativeUDT.Select(0, readfds, ref readlen, writefds, ref writelen, exceptfds, ref exceptlen, ref socketTime);
}
else
{
result = NativeUDT.Select(0, readfds, ref readlen, writefds, ref writelen, exceptfds, ref exceptlen, IntPtr.Zero);
}
SelectFileDescriptor(checkRead, readfds, readlen);
SelectFileDescriptor(checkWrite, writefds, writelen);
SelectFileDescriptor(checkError, exceptfds, exceptlen);
return result;
}
private static void SelectFileDescriptor(IList<UDTSocket> socketList, IntPtr[] fileDescriptorSet, int len)
{
if ((socketList != null) && (socketList.Count != 0))
{
if (len == 0)
{
socketList.Clear();
}
else
{
lock (socketList)
{
for (int i = 0; i < socketList.Count; i++)
{
UDTSocket socket = socketList[i];
int num2 = 0;
while (num2 < len)
{
if (fileDescriptorSet[num2] == socket.Handle)
{
break;
}
num2++;
}
if (num2 == ((int)fileDescriptorSet[0]))
{
socketList.RemoveAt(i--);
}
}
}
}
}
}
private static IntPtr[] SocketListToFileDescriptorSet(IList<UDTSocket> socketList)
{
if ((socketList == null) || (socketList.Count == 0))
{
return null;
}
IntPtr[] ptrArray = new IntPtr[socketList.Count];
for (int i = 0; i < socketList.Count; i++)
{
ptrArray[i] = socketList[i].Handle;
}
return ptrArray;
}
public override bool IsExpaired()
{
return false;
}
protected override void SingleDispose()
{
NativeUDT.Close(this.Handle);
if (this.bindSocket != null)
{
this.bindSocket.Dispose();
}
}
}
Collect.cs
public abstract class Collect : ICollect
{
~Collect()
{
this.Dispose();
}
public abstract bool IsExpaired();
private long dispoing = 0;
public bool IsDisposed
{
get
{
return Interlocked.Read(ref dispoing) == 0 ? false : true;
}
}
protected abstract void SingleDispose();
public void Dispose()
{
if (Interlocked.Exchange(ref dispoing, 1) == 0)
{
this.SingleDispose();
}
GC.SuppressFinalize(this);
}
}
调用方法
private UDTSocket CreateSocket(string ip = "0.0.0.0", int port = 0, bool rendezvous = false)
{
UDTSocket sock = new UDTSocket(AddressFamily.InterNetwork, SocketType.Stream);
int bufferSize = 64000;
sock.UDTSendBufferSize = sock.UDTReviceBufferSize = sock.UDPReviceBufferSize = sock.UDPSendBufferSize = bufferSize;
sock.WindowSize = 16;
sock.IsRendezvous = rendezvous;
sock.IsClosedLinger = false;
sock.IsReuseAddress = true;
sock.MSS = (int)this.numMTU.Value;
sock.Bind("0.0.0.0", port);
return sock;
}
呵呵 第一次写博客