/******************************************************************
* 函数介绍:限制一个Connection的网络流量
* 输入参数:nProtocol:要限制流量的协议类型
pzSrcIp:源IP
nSrcPort:源端口
pzDstIp:目标IP
nDstPort:目标端口
nTraffic:限制流量
* 输出参数:
* 返回值 :成功返回0;失败返回错误码
*******************************************************************/
注意:设置网段流量限制的函数和这个函数大体相同
int CTrafficControl::AddTrafficControl(
int nProtocol,
const char *pzSrcIp,
const int nSrcPort,
const char *pzDstIp,
const int nDstPort,
int nTraffic
)
{
HANDLE ClientHandle;
HANDLE ifcHandle;
HANDLE flowHandle;
HANDLE FilterHandle;
// QOS函数列表,处理各种事件通知回调函数
TCI_CLIENT_FUNC_LIST QoSFunctions;
= NULL;
= NULL;
= NULL;
= (TCI_NOTIFY_HANDLER)MyClNotifyHandler;
// 注册Client,获取Client句柄
long result = TcRegisterClient(CURRENT_TCI_VERSION, NULL, &QoSFunctions , &ClientHandle);
if( NO_ERROR != result )
{
//cout << "TcRegisterClient error" << endl;
return result;
}
// 获取TC接口。枚举接口->根据接口名称打开接口
TC_IFC_DESCRIPTOR InterfaceBuffer[40];
PTC_IFC_DESCRIPTOR pInterfaceBuffer = &InterfaceBuffer[0];
ULONG BufferSize = 40 * sizeof(TC_IFC_DESCRIPTOR);
result = TcEnumerateInterfaces(ClientHandle, &BufferSize, pInterfaceBuffer);
if( NO_ERROR != result )
{
//cout << "TcEnumerateInterfaces error:" << result << endl;
return result;
}
// 打开接口。注1:项目编码请使用Unicode编码,否则这里会出错,出现ERROR_NOT_FOUND找不到接口的错误。
result = TcOpenInterface( InterfaceBuffer[0].pInterfaceName, ClientHandle, NULL, &ifcHandle );
if( NO_ERROR != result )
{
//cout << "TcOpenInterface error:" << result << endl;
return result;
}
// 创建一个Flow,下面是关键代码
int curSize = sizeof(TC_GEN_FLOW) + sizeof(QOS_DS_CLASS) + sizeof(QOS_TRAFFIC_CLASS) + sizeof(QOS_OBJECT_HDR);
char *bufFlow = new char[curSize];
PTC_GEN_FLOW newFlow = ( PTC_GEN_FLOW )bufFlow;
LPQOS_OBJECT_HDR objHdr = NULL;
// 设置FlowerSpec属性. SetFlowSpec函数实现参见附件中的代码
FLOWSPEC sendFlowspec, recvFlowspec;
SetFlowSpec( sendFlowspec, nTraffic, SERVICETYPE_QUALITATIVE );
SetFlowSpec( recvFlowspec, nTraffic, SERVICETYPE_QUALITATIVE );
newFlow->SendingFlowspec = sendFlowspec;
newFlow->ReceivingFlowspec = recvFlowspec;
newFlow-> TcObjectsLength = sizeof(QOS_DS_CLASS) + sizeof(QOS_TRAFFIC_CLASS) + sizeof(QOS_OBJECT_HDR);
LPQOS_DS_CLASS pQOSClass = (LPQOS_DS_CLASS)(&(newFlow-> TcObjects[0]) );
pQOSClass-> = QOS_OBJECT_DS_CLASS;
pQOSClass-> = sizeof(QOS_DS_CLASS);
pQOSClass-> DSField = 0x24;
LPQOS_TRAFFIC_CLASS pTRClass = (LPQOS_TRAFFIC_CLASS)((char*)&(newFlow-> TcObjects[0])+ sizeof(QOS_DS_CLASS));
pTRClass-> = QOS_OBJECT_TRAFFIC_CLASS;
pTRClass-> = sizeof(QOS_TRAFFIC_CLASS);
pTRClass-> TrafficClass = 0x3;
objHdr = (LPQOS_OBJECT_HDR)((char *)&(newFlow-> TcObjects[0]) + sizeof(QOS_DS_CLASS) + sizeof (QOS_TRAFFIC_CLASS));
objHdr-> ObjectType = QOS_OBJECT_END_OF_LIST;
objHdr-> ObjectLength = sizeof(QOS_OBJECT_HDR);
// 添加Flow到打开的接口中。
// 注意,FlowSpec设置错误会导致这里添加失败。相关规则请参见MSDN中FLOWSPEC的解释
result = TcAddFlow( ifcHandle, /*ClientHandle*/NULL, 0, newFlow, &flowHandle );
if( NO_ERROR != result )
{
//cout << "TcAddFlow Error::" << result << endl;
return result;
}
// 创建Filter。
// Flow设定了流量的限制,Filter设定需要限制流量的条件
TC_GEN_FILTER GenericFilter;
IP_PATTERN Pattern, Mask;
memset(&Pattern,0,sizeof(IP_PATTERN));
memset(&Mask,0,sizeof(IP_PATTERN));
= NDIS_PROTOCOL_ID_TCP_IP; // TCP/IP
= sizeof(IP_PATTERN);
= &Pattern; // pattern to match, defined below
= &Mask;
// 过滤器模式
// 根据源、目标ip和端口,我们可以过滤到一个特定的连接。
// 如果是过滤一个网段,需要用到Mask参数。
Pattern.Reserved1 = 0;
Pattern.Reserved2 = 0;
= inet_addr( pzSrcIp ); // 源IP
= inet_addr( pzDstIp ); // 目标IP
= htons( nSrcPort ); // 源端口
= htons( nDstPort ); // 目标端口
= nProtocol; // 协议类型。TCP or UDP or else
Pattern.Reserved3[0] = 0;
Pattern.Reserved3[1] = 0;
Pattern.Reserved3[2] = 0;
// 掩码。设置Pattern中哪些位是有效的,也就是IP地址中的掩码
// 如要限制212.73.0.0这个网段与本地之间的流量,掩码设置为255.255.0.0
Mask.Reserved1 = 0;
Mask.Reserved2 = 0;
= htonl( 0xFFFFFFFF );
= htonl(0xFFFFFFFF);
= htons( 0xFFFF );
= htons( 0xFFFF );
= nProtocol;
Mask.Reserved3[0] = 0;
Mask.Reserved3[1] = 0;
result = TcAddFilter(flowHandle, &GenericFilter, &FilterHandle);
if( NO_ERROR != result )
{
//cout << "TcAddFilter error:" << result << endl;
return result;
}
return result;
}