这是我自己在某论坛上发的一篇水贴:http://www.sufeinet.com/thread-9275-1-2.html,原理和解释,我就直接重发一遍在自己博客上了。
时隔一个月 回来把之前的坑填上。之前发的两篇文章链接如下: http://www.sufeinet.com/thread-8876-1-1.html,http://www.sufeinet.com/thread-8882-1-1.html
跟之前的区别在于 这一次是完整 真正可用的代码 可以完全用于商业目的 因为我已经不间断的跑了一个月 没有任何问题。
异步实现的最大坑在于 你发出一个异步请求之后 你可能收不到任何响应 ,你发出的包,可能在Internet上看风景去了,漫游去了,或者被各种延迟,各种阻塞,或者被路由器负载脱落,各种丢失,TCP建立起的连接对应于网络层的VC(虚电路)可能以各种形式断开然后你永远不会知道。。
所以 由于网络层的各种不稳定 所以在传输层你必须建立起稳妥的解决方案 将控制权把握在自己手上。
解决方案很简单。计数器而已。 计数器让线程池帮我们做就好了:
System.Threading.ThreadPool.RegisterWaitForSingleObject(m_ar.AsyncWaitHandle,
TimeoutCallback, pa, MyAsyncPara.DefaultTimeOutSpan, true);
这段代码使用一个信号量,用CLR的用户模式构造 System.Threading.Interlocked.Increment(ref pa.m_semaphore) != 1 超时便不再处理数据
OK了,现在来看看调用:
HttpItems hi = new HttpItems();
AsyncHttpHelper wh = new AsyncHttpHelper();
hi.URL = urlinfo.Url;
wh.GetHtmlDataAsync(hi, YourCallBackMethod);
void YourCallBackMethod(HttpResults result)
{
}
好了 代码跑起来的效果就是,一个线程处理处理一堆爬取任务速度飞快有木有!绝对不卡当前线程有木有!
最后提2点注意事项:
1 以太网协议的最大允许字节为1500多 无线局域网的最大允许字节为2200多 IP协议最大允许字节为65500多 为了让爬虫适合在任意网络上执行 缓存区设置为1KB比较合适
2 同学们 请对你们自己注入IP网络的数据包负责 因为不管是电脑还是路由器 他们的TCP栈大小总是有限的 过多的数据注入 会导致丢包 网络拥塞 ,请慎重计算你要注入网络的数据包量。一句话 不要无限制的发起请求 因为多的请求最终会超时 而你很可能是造成网络拥塞的元凶。
欢迎测试或拍砖。
源代码改日上传(。。我忘了论坛密码,或者直接上论坛上下载也可。)论坛上下载次数已经接近两百次。
觉得用得上,您就点个赞。