1

我是一个使用.TAP 模式API编写的网络爬虫HttpWebRequest

我想从中下载一些东西,http://somedomain.tld但我最终可能会发送相当多的请求。我不知道是否somedomain.tld会及时回复,我希望每个请求不超过 10 秒以完成发回回复。我还想利用ServicePoint该域强制执行的连接限制。

所以我需要能够根据请求超时。通常,我会从 a 获得取消令牌CancellationTokenSource

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10d))

并将其提供给我的异步操作,也许还注册一个调用的取消回调myWebRequest.Abort(),所以我最终得到一个看起来像这样的(简化)方法:

public async Task<byte[]> GetResponseData(Uri uri, CancellationToken ct)
{
    var wr = (HttpWebRequest)WebRequest.Create(uri);
    ct.Register(wr.Abort);
    using(var response = await wr.GetResponseAsync())
    using(var ms = new MemoryStream())
    using(var responseStream = response.GetResponseStream())
    {
        await responseStream.CopyToAsync(ms,4096,ct);
        return ms.ToArray();
    }

}

到目前为止,一切都很好。

让我稍微限制一下:

var uri = new Uri("http://somedomain.tld");
var sp = ServicePointManager.FindServicePoint(uri);
sp.ConnectionLimit = 1;

现在,ServicePoint关联的实例somedomain.tld一次只允许一个请求。

现在我同时发出两个请求,安全地知道这ServicePoint将使目标域免受我的滥用:

var dataTasks = Enumerable.Range(0,2).Select(async _=>{
    using(var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10d)))
    {
        return await GetResponseData(uri,cts.Token);
    }
});

var datas = await Task.WhenAll(dataTasks);

现在,让我们假设第一个请求需要超过 10 秒才能完成......因为我已经限制ServicePoint一次只触发一个请求,ServicePoint当轮到触发第二个请求时,它已经被取消并且中止。

那么我怎么知道请求实际上是什么时候发送的呢?如何设置“知道”ServicePoint与特定请求有关的操作的超时?

4

0 回答 0