本节介绍在UDT源代码中所有使用的数据结构
CUDTSocket:描述UDT SOCKET
class CUDTSocket
{
UDTSTATUS m_Status; //当前UDT SOCKET的状态
uint64_t m_TimeStamp; //UDT SOCKET关闭的时间
int m_iIPversion; //IP Version
sockaddr* m_pSelfAddr; // pointer to the local address of the socket
sockaddr* m_pPeerAddr; // pointer to the peer address of the socket
UDTSOCKET m_SocketID; // socket ID
UDTSOCKET m_ListenSocket; // ID of the listener socket; 0 means this is an independent socket
UDTSOCKET m_PeerID; // peer socket ID
int32_t m_iISN; //初始化序列号,用来告知来自相同的IP:Port的不同的连接
CUDT* m_pUDT; // pointer to the UDT entity
std::set<UDTSOCKET>* m_pQueuedSockets; //连接已完成,等待accept()调用的队列
std::set<UDTSOCKET>* m_pAcceptSockets; //已经完成accept()的队列
udt_pthread_cond_t m_AcceptCond; // used to block "accept" call
udt_pthread_mutex_t m_AcceptLock; // mutex associated to m_AcceptCond
unsigned int m_uiBackLog; //Listener中的最大连接数
int m_iMuxID; //资源复用器ID
udt_pthread_mutex_t m_ControlLock; // lock this socket exclusively for control APIs: bind/listen/connect
private:
CUDTSocket(const CUDTSocket&);
CUDTSocket& operator=(const CUDTSocket&);
};
UDTSTATUS:描述UDT SOCKET状态
enum UDTSTATUS {INIT = 1, OPENED, LISTENING, CONNECTING, CONNECTED, BROKEN, CLOSING, CLOSED, NONEXIST};
CUDTUnited:全局管理者,保存所有的UDT SOCKET
class CUDTUnited
{
std::map<UDTSOCKET, CUDTSocket*> m_Sockets; //保存所有的UDT SOCKET实例
udt_pthread_mutex_t m_ControlLock;
udt_pthread_mutex_t m_IDLock;
UDTSOCKET m_SocketID; //每一次启动时都会创建一个唯一的SOCKET ID
std::map<int64_t, std::set<UDTSOCKET> > m_PeerRec; //记录来自对方套接字的连接以避免重读的请求,int64_t = (socker_id << 30) + isn
private:
udt_pthread_key_t m_TLSError; //线程局部的错误反馈,还不如使用全局变量呢..
#ifndef WINDOWS
static void TLSDestroy(void* e) {if (NULL != e) delete (CUDTException*)e;}
#else
std::map<DWORD, CUDTException*> m_mTLSRecord;
void checkTLSValue();
udt_pthread_mutex_t m_TLSLock;
#endif
private:
std::map<int, CMultiplexer> m_mMultiplexer; // UDP multiplexer(复用器),不过我一直没有搞懂代表什么意思
udt_pthread_mutex_t m_MultiplexerLock;
private:
CCache<CInfoBlock>* m_pCache; // UDT network information cache
private:
volatile bool m_bClosing; //目前的状态是否为关闭的,主要用于调整GC线程
udt_pthread_mutex_t m_GCStopLock;
udt_pthread_cond_t m_GCStopCond;
udt_pthread_mutex_t m_InitLock;
int m_iInstanceCount; //记录调用startup()的次数
bool m_bGCStatus; //判断GC线程是否在工作
udt_pthread_t m_GCThread;
#ifndef WINDOWS
static void* garbageCollect(void*);
#else
static DWORD WINAPI garbageCollect(LPVOID);
#endif
std::map<UDTSOCKET, CUDTSocket*> m_ClosedSockets; //暂时存放关闭的UDT SOCKET
void checkBrokenSockets();
void removeSocket(const UDTSOCKET u);
private:
CEPoll m_EPoll; //事件处理器
private:
CUDTUnited(const CUDTUnited&);
CUDTUnited& operator=(const CUDTUnited&);
};
CMultiplexer:资源复用器,他是所有资源的实际所有者,其他的都只是引用(目前我是这样理解的)
struct CMultiplexer
{
CSndQueue* m_pSndQueue; // The sending queue
CRcvQueue* m_pRcvQueue; // The receiving queue
CChannel* m_pChannel; // The UDP channel for sending and receiving
CTimer* m_pTimer; // The timer
int m_iPort; // The UDP port number of this multiplexer
int m_iIPversion; // IP version
int m_iMSS; // Maximum Segment Size
int m_iRefCount; //与此资源复用器相关联的UDT实例的数量
bool m_bReusable; //这个资源复用器是否可以被共享
int m_iID; // multiplexer ID
};
CCache:使用HASH缓存信息(Vector+List)
template<typename T> class CCache
{
private:
std::list<T*> m_StorageList;
typedef typename std::list<T*>::iterator ItemPtr;
typedef std::list<ItemPtr> ItemPtrList;
std::vector<ItemPtrList> m_vHashPtr;
int m_iMaxSize; //1024
int m_iHashSize; //1024*3
int m_iCurrSize; //0
udt_pthread_mutex_t m_Lock;
private:
CCache(const CCache&);
CCache& operator=(const CCache&);
};
CInfoBlock
class CInfoBlock
{
public:
uint32_t m_piIP[4]; //机器可读的IP地址,为了IPV4只占32位,IPV6全部占用
int m_iIPversion; // IP version
uint64_t m_ullTimeStamp; //上一次更新的时间
int m_iRTT; //RTT
int m_iBandwidth; //估计的带宽
int m_iLossRate; //平均丢失速率
int m_iReorderDistance; //数据包重新排序距离
double m_dInterval; //分组间时间,就是数据包发送的间隔时间,用于拥塞控制
double m_dCWnd; //拥塞窗口大小用于拥塞控制
}
CEpoll:别具一格的EPoll,存在一组EPoll管理一组事件
class CEPoll
{
int m_iIDSeed; //new时创建的随机ID
udt_pthread_mutex_t m_SeedLock;
std::map<int, CEPollDesc> m_mPolls; // all epolls
udt_pthread_mutex_t m_EPollLock;
};
CEPollDesc:描述具体关注的事件:人为管理的UDT事件以及系统管理的UDP事件
struct CEPollDesc
{
int m_iID; // epoll ID
std::set<UDTSOCKET> m_sUDTSocksOut; // set of UDT sockets waiting for write events
std::set<UDTSOCKET> m_sUDTSocksIn; // set of UDT sockets waiting for read events
std::set<UDTSOCKET> m_sUDTSocksEx; // set of UDT sockets waiting for exceptions
int m_iLocalID; // local system epoll ID
std::set<SYSSOCKET> m_sLocals; // set of local (non-UDT) descriptors
std::set<UDTSOCKET> m_sUDTWrites; // UDT sockets ready for write
std::set<UDTSOCKET> m_sUDTReads; // UDT sockets ready for read
std::set<UDTSOCKET> m_sUDTExcepts; // UDT sockets with exceptions (connection broken, etc.)
};
CUDT:全局最复杂的一个类,用于描述一个UDT连接
class CUDT {
static CUDTUnited s_UDTUnited; //静态变量,所有的CUDT共享的全局管理对象
public:
static const UDTSOCKET INVALID_SOCK; //初始化无效的UDT SOCKET = -1
static const int ERROR; //初始化错误
private:
UDTSOCKET m_SocketID; // UDT socket number
UDTSockType m_iSockType; //TCP / UDP
UDTSOCKET m_PeerID; // peer id, for multiplexer
static const int m_iVersion; // UDT version, for compatibility use
private:
int m_iPktSize; // Maximum/regular packet size, in bytes
int m_iPayloadSize; // Maximum/regular payload(有效载荷) size, in bytes
private:
int m_iMSS; // Maximum Segment Size, in bytes
bool m_bSynSending; // 发送同步模式
bool m_bSynRecving; // 接收同步模式
int m_iFlightFlagSize; // 来自对端的最大的数据包传输量
int m_iSndBufSize; //UDT最大的发送缓冲大小
int m_iRcvBufSize; //UDT最大的接收缓冲区大小
linger m_Linger; //如果使用了Linger选项,Struct Linger
int m_iUDPSndBufSize; //UDP发送缓冲区大小
int m_iUDPRcvBufSize; //UDP接收缓冲区大小
int m_iIPversion; // IP version
bool m_bRendezvous; //交会连接模式
int m_iSndTimeOut; //发送超时时间(ms)
int m_iRcvTimeOut; //接收超时时间(ms)
bool m_bReuseAddr; //是否重用UDP端口
int64_t m_llMaxBW; //最大的数据传输速率(阀值)
private:
CCCVirtualFactory * m_pCCFactory; // 为了提供特殊的拥塞控制接口
CCC * m_pCC; // 拥塞控制接口
CCache < CInfoBlock > *m_pCache; // 管理连接缓存
private:
volatile bool m_bListening; // 是否正在监听中?
volatile bool m_bConnecting; // 是否处于连接中?连接未完成
volatile bool m_bConnected; // 连接已完成
volatile bool m_bClosing; // 是否处于关闭过程中?未完成
volatile bool m_bShutdown; // 对方的连接是否调用了shutdown?
volatile bool m_bBroken; // 连接是否已经损坏?
volatile bool m_bPeerHealth; // 对等方是否依旧正常?
bool m_bOpened; // UDT是否已经打开?
int m_iBrokenCounter; // 一个计数器,记录目前处于Broken状态的UDT SOCKET,由GC线程使用
int m_iEXPCount; // 异常计数器
int m_iBandwidth; // 估计带宽(packets / second)
int m_iRTT; // RTT(ms)
int m_iRTTVar; // RTT方差
int m_iDeliveryRate; // 对方的接收速率(packets / second)
uint64_t m_ullLingerExpiration; //异常连接终止时的等待时间
CHandShake m_ConnReq; // connection request
CHandShake m_ConnRes; // connection response
int64_t m_llLastReqTime; // last time when a connection request is sent
private:
CSndBuffer * m_pSndBuffer; // Sender buffer(SendQueue是针对UDP使用的,SendBuffer是针对UDT使用的)
CSndLossList * m_pSndLossList; // Sender loss list
CPktTimeWindow * m_pSndTimeWindow; // 数据包发送时间窗口
volatile uint64_t m_ullInterval; //数据包发送时间间隔, 使用CPU周期计数
uint64_t m_ullTimeDiff; // 数据包间时间的差异
volatile int m_iFlowWindowSize; // 流量控制窗口大小
volatile double m_dCongestionWindow; // 拥塞窗口大小
volatile int32_t m_iSndLastAck; // 上一次收到的ACK序列号
volatile int32_t m_iSndLastDataAck; // 最后一个用于更新发送缓冲区和丢失链表的ACK
volatile int32_t m_iSndCurrSeqNo; // 已发送的最大的序列号
int32_t m_iLastDecSeq; // 发送的最后一次减少的序列号
int32_t m_iSndLastAck2; // 最后送回的ACK2
uint64_t m_ullSndLastAck2Time; // 最后送回的ACK2的时间
int32_t m_iISN; // 初始序列号
private:
CRcvBuffer * m_pRcvBuffer; // Receiver buffer
CRcvLossList * m_pRcvLossList; // Receiver loss list
CACKWindow * m_pACKWindow; // 收到的ACK历史窗口
CPktTimeWindow * m_pRcvTimeWindow; // 数据包到达时间窗口
int32_t m_iRcvLastAck; // 上一次接收的ACK
uint64_t m_ullLastAckTime; // 上一次接收ACK的时间
int32_t m_iRcvLastAckAck; // 最后接收的已确认的ACK
int32_t m_iAckSeqNo; // 最后接收的ACK序列号
int32_t m_iRcvCurrSeqNo; // 收到的最大的序列号
uint64_t m_ullLastWarningTime; // 上一次收到警告信息的时间
int32_t m_iPeerISN; // 对方的初始化序列号
private:
udt_pthread_mutex_t m_ConnectionLock; // used to synchronize connection operation
udt_pthread_cond_t m_SendBlockCond; // used to block "send" call
udt_pthread_mutex_t m_SendBlockLock; // lock associated to m_SendBlockCond
udt_pthread_mutex_t m_AckLock; // used to protected sender's loss list when processing ACK
udt_pthread_cond_t m_RecvDataCond; // used to block "recv" when there is no data
udt_pthread_mutex_t m_RecvDataLock; // lock associated to m_RecvDataCond
udt_pthread_mutex_t m_SendLock; // used to synchronize "send" call
udt_pthread_mutex_t m_RecvLock; // used to synchronize "recv" call
private:
uint64_t m_StartTime; // UDT的启动时间
int64_t m_llSentTotal; // 发送的数据包总数,包括重传
int64_t m_llRecvTotal; // 收到的数据包总数
int m_iSndLossTotal; // 发送端丢失的数据包总数
int m_iRcvLossTotal; // 接收端丢失的数据包总数
int m_iRetransTotal; // 重传的数据包总数
int m_iSentACKTotal; // 发送的ACK数据包总数
int m_iRecvACKTotal; // 收到的ACK数据包总数
int m_iSentNAKTotal; // 发送的NAK数据包总数
int m_iRecvNAKTotal; // 收到的NAK数据包总数
int64_t m_llSndDurationTotal; // 总的实时发送时间
uint64_t m_LastSampleTime; // 最后的性能采样时间
int64_t m_llTraceSent; // 在最后一个跟踪的时间间隔内发送的数据包数量
int64_t m_llTraceRecv; // 在最后一个跟踪的时间间隔内接收的数据包总量
int m_iTraceSndLoss; // 发送端在最后一个跟踪的时间间隔内发送的数据包数量
int m_iTraceRcvLoss; // 接收端的最后一个跟踪的时间间隔内接收的数据包数量
int m_iTraceRetrans; // 在最后一个跟踪的时间间隔内重传的数据包数量
int m_iSentACK; // 在最后一个跟踪的时间间隔内发送的ACK数据包数量
int m_iRecvACK; // 在最后一个跟踪的时间间隔内接受的ACK数据包数量
int m_iSentNAK; // 在最后一个跟踪的时间间隔内发送的NAK数据包数量
int m_iRecvNAK; // 在最后一个跟踪的时间间隔内接收的NAK数据包数量
int64_t m_llSndDuration; // 发送真正花费的时间
int64_t m_llSndDurationCounter; // 使用定时器来记录持续发送的时间
private:
uint64_t m_ullCPUFrequency; // CPU时钟频率, used for Timer, ticks per microsecond
static const int m_iSYNInterval; // 周期性速率控制间隔, 10000 microsecond
static const int m_iSelfClockInterval; // ACK时钟间隔
uint64_t m_ullNextACKTime; // 下一次ACK到期时间,使用CPU时钟周期
uint64_t m_ullNextNAKTime; // 下一次NAK到期时间,使用CPU时钟周期
volatile uint64_t m_ullSYNInt; // SYN时间间隔,使用CPU时钟周期
volatile uint64_t m_ullACKInt; // ACK时间间隔,使用CPU时钟周期
volatile uint64_t m_ullNAKInt; // NAK时间间隔,使用CPU时钟周期
volatile uint64_t m_ullLastRspTime; // 对方最后一次回复的时间
uint64_t m_ullMinNakInt; // NAK超时下限,太小的值可能会引起不必要的重传
uint64_t m_ullMinExpInt; // 超时下限阀值,太小的值会导致问题
int m_iPktCount; // 收到的ACK计数
int m_iLightACKCount; // 轻量级的ACK计数
uint64_t m_ullTargetTime; // 下一个数据包发送的预计时间
private:
// for UDP multiplexer
CSndQueue * m_pSndQueue; // 数据包发送队列
CRcvQueue * m_pRcvQueue; // 数据包接收队列
sockaddr * m_pPeerAddr; // 对方的地址
uint32_t m_piSelfIP[4]; // 本地的IP地址
CSNode * m_pSNode; // 发送队列Node(堆)
CRNode * m_pRNode; // 接收队列Node(双向链表)
private:
std::set < int > m_sPollID; //所有的EpollID
};
CSndBuffer:UDT SOCKET Send Buffer
class CSndBuffer
{
private:
udt_pthread_mutex_t m_BufLock; // used to synchronize buffer operation
struct Block //为了方便的提交给SendQueue
{
char* m_pcData; // 指向数据块
int m_iLength; // 数据块的长度
int32_t m_iMsgNo; // 数据块的编号
uint64_t m_OriginTime; // 原始请求时间
int m_iTTL; // TTL(ms)
Block* m_pNext; // next block
} *m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock;
// m_pBlock: The head pointer
// m_pFirstBlock: The first block
// m_pCurrBlock: The current block
// m_pLastBlock: The last block (if first == last, buffer is empty)
struct Buffer //真实的存储Buffer
{
char* m_pcData; // buffer
int m_iSize; // size
Buffer* m_pNext; // next buffer
} *m_pBuffer; // physical buffer
int32_t m_iNextMsgNo; //下一条消息编号
int m_iSize; // 32 (number of packets)
int m_iMSS; // 1500
int m_iCount; // 已经使用的Blocks
};
CRecvBuffer:UDT SOCKET Recv Buffer
class CRcvBuffer
{
private:
CUnit** m_pUnit; // 数据缓冲Buffer
int m_iSize; // 65536(bytes)
CUnitQueue* m_pUnitQueue; // 共享的接收队列
int m_iStartPos; // 开始读取data的位置
int m_iLastAckPos; // 上一次被确认的位置,start~lastpos之间的数据可读
// EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1
int m_iMaxPos; // 数据存在的最大的位置,还没有被确认
int m_iNotch; // 第一个CUnit的读取点
};
CPacket:数据包的封装
class CPacket
{
public:
int32_t& m_iSeqNo; // sequence number
int32_t& m_iMsgNo; // message number
int32_t& m_iTimeStamp; // timestamp
int32_t& m_iID; // socket ID
char*& m_pcData; // data/control information
static const int m_iPktHdrSize; // packet header size = 16
protected:
uint32_t m_nHeader[4]; // The 128-bit header field
iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data]
int32_t __pad;
};
CHandShake:握手包
class CHandShake
{
public:
static const int m_iContentSize; // Size of hand shake = 48
public:
int32_t m_iVersion; // UDT version
int32_t m_iType; // UDT socket type:TCP/UDP
int32_t m_iISN; // 随机的初始化序列号
int32_t m_iMSS; // maximum segment size
int32_t m_iFlightFlagSize; // flow control window size
int32_t m_iReqType; // 1: regular connection request, 0: rendezvous(交会连接请求) connection request, -1/-2: response
int32_t m_iID; // socket ID
int32_t m_iCookie; // cookie
uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to
};
CUnit:对于Packet的简单封装
struct CUnit
{
CPacket m_Packet; // packet
int m_iFlag; // 0: free 1:occupid, 2: msg已经read,但是还没有被free, 3: msg被丢弃
};
CUnitQueue:类似HASH那样组织CUnit Queue
class CUnitQueue
{
private:
struct CQEntry
{
CUnit* m_pUnit; // unit queue
char* m_pBuffer; // data buffer
int m_iSize; // size of each queue
CQEntry* m_pNext;
}
*m_pQEntry, // 指向起始的Entry队列
*m_pCurrQueue, // 指向当前的Entry队列
*m_pLastQueue; // 指向最后一个Entry队列
CUnit* m_pAvailUnit; //最近访问的Unit*
int m_iSize; // 总共的Packets数量
int m_iCount; // 已经使用的Packets数量
int m_iMSS; // unit buffer size
int m_iIPversion; // IP version
};
CSNode:Send List Node
struct CSNode
{
CUDT* m_pUDT; // 指向CUDT*的指针
uint64_t m_llTimeStamp; // 堆化时排序的时间戳
int m_iHeapLoc; // 堆的层次,-1意味着暂时不存在与当前堆中
};
CSndList:Send List,使用堆对即将发送的packet进行组织
class CSndUList
{
private:
CSNode** m_pHeap; // 堆化数组
int m_iArrayLength; // 堆数组长度
int m_iLastEntry; // 最近一次发送的位置
udt_pthread_mutex_t m_ListLock;
udt_pthread_mutex_t* m_pWindowLock;
udt_pthread_cond_t* m_pWindowCond;
CTimer* m_pTimer;
};
CRNode:Recv List Node
struct CRNode
{
CUDT* m_pUDT; // Pointer to CUDT*
uint64_t m_llTimeStamp; // Time Stamp
CRNode* m_pPrev; // previous link
CRNode* m_pNext; // next link
bool m_bOnList; // 当前节点是否在双向链表上
};
CRcvUList:用于接收packet的双向链表
class CRcvUList
{
public:
CRNode* m_pUList; // the head node
private:
CRNode* m_pLast; // the last node
};
CHash:Hash表
class CHash
{
private:
struct CBucket
{
int32_t m_iID; // Socket ID
CUDT* m_pUDT; // Socket instance
CBucket* m_pNext; // next bucket
} **m_pBucket; // list of buckets (the hash table)
int m_iHashSize; // size of hash table
};
CRendezvousQueue:交汇连接队列
class CRendezvousQueue
{
private:
struct CRL
{
UDTSOCKET m_iID; // UDT socket ID (self)
CUDT* m_pUDT; // UDT instance
int m_iIPversion; // IP version
sockaddr* m_pPeerAddr; // UDT sonnection peer address
uint64_t m_ullTTL; // the time that this request expires
};
std::list<CRL> m_lRendezvousID; // The sockets currently in rendezvous mode
udt_pthread_mutex_t m_RIDVectorLock;
};
CSndQueue:Send Queue
class CSndQueue
{
private:
static void* worker(void* param); //发送线程
udt_pthread_t m_WorkerThread;
private:
CSndUList* m_pSndUList; // 堆化的Send List
CChannel* m_pChannel; // The UDP channel for data sending
CTimer* m_pTimer; // 定时器设施
udt_pthread_mutex_t m_WindowLock;
udt_pthread_cond_t m_WindowCond;
volatile bool m_bClosing; // 发送线程是否启动
udt_pthread_cond_t m_ExitCond;
};
CRcvQueue:Recv Queue
class CRcvQueue
{
private:
static void* worker(void* param); //接收线程
udt_pthread_t m_WorkerThread;
private:
CUnitQueue m_UnitQueue; // The received packet queue(就是那个类似于Hash的组织)
CRcvUList* m_pRcvUList; // 这个List中的UDT实例准备从Queue中读取数据
CHash* m_pHash; // HASH可以加速在List中寻找UDT实例
CChannel* m_pChannel; // UDP channel for receving packets
CTimer* m_pTimer; // 与发送队列共享Timer
int m_iPayloadSize; // packet中的有效载荷
volatile bool m_bClosing; // 接收线程是否启动
udt_pthread_cond_t m_ExitCond;
private:
udt_pthread_mutex_t m_LSLock;
CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity
CRendezvousQueue* m_pRendezvousQueue; // 汇合模式中的UDT SOCKET列表
std::vector<CUDT*> m_vNewEntry; // 新添加的条目
udt_pthread_mutex_t m_IDLock;
std::map<int32_t, std::queue<CPacket*> > m_mBuffer; // 用于集合连接请求的临时缓冲区
udt_pthread_mutex_t m_PassLock;
udt_pthread_cond_t m_PassCond;
};
CChannel:描述UDP,用于数据发送
class CChannel
{
private:
int m_iIPversion; // IP version
int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test)
UDPSOCKET m_iSocket; // socket descriptor
int m_iSndBufSize; // UDP sending buffer size
int m_iRcvBufSize; // UDP receiving buffer size
};
CTimer:定时器设施
class CTimer
{
private:
uint64_t m_ullSchedTime; //下一次被调度的时间
udt_pthread_cond_t m_TickCond;
udt_pthread_mutex_t m_TickLock;
static udt_pthread_cond_t m_EventCond;
static udt_pthread_mutex_t m_EventLock;
private:
static uint64_t s_ullCPUFrequency; // CPU的时钟频率
static uint64_t readCPUFrequency();
static bool m_bUseMicroSecond; // use gettimeofday().
};
CACKWindow:记录ACK时间的窗口
class CACKWindow
{
private:
int32_t* m_piACKSeqNo; // 记录ACK序列号
int32_t* m_piACK; // 记录数据序列号
uint64_t* m_pTimeStamp; //记录ACK的发送时间
int m_iSize; // ACK窗口的大小
int m_iHead; // 记录最后一次ACK
int m_iTail; // 记录存在时间最长的ACK
};
CPktTimeWindow:记录数据包的时间窗口
class CPktTimeWindow
{
private:
int m_iAWSize; // 分组到达时历史窗口的大小
int* m_piPktWindow; // 分组信息窗口
int* m_piPktReplica;
int m_iPktWindowPtr; // 分组信息窗口的位置指针
int m_iPWSize; // 探测历史窗口打下
int* m_piProbeWindow; // 记录用于探测分组的分组间时间
int* m_piProbeReplica;
int m_iProbeWindowPtr; // 位置指针指向探测窗口
int m_iLastSentTime; // 最后一个packet的发送时间
int m_iMinPktSndInt; // 最小的包发送时间间隔
uint64_t m_LastArrTime; // 最后一个包的到达时间
uint64_t m_CurrArrTime; // 当前包的到达时间
uint64_t m_ProbeTime; // 第一个探测分组的到达时间
};