当前位置:编程学习 > 网站相关 >>

如何控制您的扫描速度

>>>1.控制线程数量 VS 控制socket数量
做页面抓取、web扫描的时候,经常有扫描速度、压力控制的要求。
以前一直是通过控制线程数的方法去控制扫描速度,但由于web响应时间不同等原因,很难有效地控制扫描速度。比如之前爬一个全是静态网页的站点,由于该网站响应速度非常快,开3个抓取线程的情况下,每秒都会完成几百个请求。
所以控制socket数量才是可靠的解决方案。

>>>2.控制socket请求数 VS 控制socket连接数
虽然给网站带来压力的更多的是连接数,而不是请求数。但是管理员往往只注意请求数,而日志里面记录的也是请求数。所以我选了第一种。

>>>3.在那一层控制
       我最先想到的方案是写一个函数: SocketControler.getConnectPermission("you website")。扫描程序每次建立socket前都使用while(SocketController.getConnectPermission("you website")==false){sleep(10);},但这样耦合性太高,你需要修改很多代码,而且这种方案在混合语言程序中无法使用。
       于是我开始在应用程序的"下一层"打主意——我可以hook socket!gethostbyname() 或者 socket!send(),在这些函数的头部添加while(SocketController.getConnectPermission("you website")==false){sleep(10);},这样有几个好处:

1.低耦合:您只需要把SocketControler.hook.dll注入扫描程序就行了,不需要修改扫描程序的任何代码
2.适合混合语言的程序,如 vc+python+perl
3.这种控制方案非常精确




>>>4.演示代码

限制每秒钟最多发30个连接:

//控制的域名总数,不用改
#define MAX_HOST 10000

//域名的最大长度,过长的域名会自动截断
#define HOST_LEN 64

//计算周期,单位为妙
int cycle = 1000;
//最大连接数
int max_connect = 30;


typedef  struct SocketController
{
char *host;
int  *connnetTimes;
int   minIndex;

};

SocketController socketController[MAX_HOST];

void ini()
{
for (int i=0;i<MAX_HOST;i++)
{
socketController[i].host = NULL;
socketController[i].connnetTimes = NULL;
}
}

int getConnet_connnets(char *host)
{
int ret = -1;
for (int i=0;i<MAX_HOST;i++)
{
if (socketController[i].host == NULL)
{
//printf("create new for %s ",host);
socketController[i].host =  (char *)malloc(sizeof(char)*HOST_LEN);
strncpy(socketController[i].host,host,HOST_LEN);
socketController[i].host[HOST_LEN-1]=;
socketController[i].connnetTimes = (int *)malloc(sizeof(int)*max_connect);
socketController[i].minIndex = 0;

for (int j=0;j<max_connect;j++)
{
socketController[i].connnetTimes[j] = 0;
}
ret = i;
break;
}
if (stricmp(socketController[i].host,host)==0)
{
//printf("find %ss Controller ",host);
ret = i;
break;
}
}
return ret;
}

int getConnet(char *host)
{

int index = getConnet_connnets(host);
if (index==-1)
{
return 1;
}
else
{
DWORD now = GetTickCount();
DWORD overdue = now-cycle; //在这个时间之前的都可以

if (socketController[index].connnetTimes[socketController[index].minIndex] <  overdue)
{
socketController[index].connnetTimes[socketController[index].minIndex]  = now;
socketController[index].minIndex ++;
if (socketController[index].minIndex== (max_connect-1) )
{
socketController[index].minIndex = 0;
}
return 1;
}
else
{
return 0;
}
}   

}

int get(char *host,int second)
{
int start = GetTickCount();
int sum = 0;
while (true)
{
if (GetTickCount()-start>=second)
{
return sum;
}

int ret = getConnet(host);
if (ret == 1)
{
sum++;
}
Sleep(10);
}
}

int main()
{

ini();

int second = 0;
second = 1000;
printf("%d second get  %d ",second,get("www.baidu.com",second));
second = 2000;
printf("%d second get  %d ",second,get("www.baidu.com",second));
second = 3000;
printf("%d second get  %d ",second,get("www.11.com",second));
second = 4000;
printf("%d second get  %d ",second,get("www.22.com",second));
second = 5000;
printf("%d second get  %d ",second,get("www.baidu.com",second));
return 1;
}

效果如下图,由于sleep(xxx)的原因,每秒钟最多发送的连接数是 (max_connect-1) :




下图为注入firefox后,firefox打开new.baidu.com的效果


补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,