我有一个控制台应用程序,它向网页发出单个请求并返回其服务器状态,例如。 200、404等.
我想应用以下更改:
用户输入列表:
- 请求的网址
- 要使用多少个并行连接(并发用户)
- 提交尽可能多的请求需要多长时间(秒)
输出列表:
- 显示总抓取次数
- 显示每秒抓取次数
- 显示平均响应时间(毫秒)
我认为最好的方法是并行运行多个 http 获取并在单个进程中运行,这样就不会导致客户端计算机陷入困境。
我真的很喜欢 C#,但我对它还是新手。我研究了有关此问题的其他文章,但我不完全理解它们,因此我们将不胜感激。
我的代码:
static void Main(string[] args)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://10.10.1.6/64k.html");
webRequest.AllowAutoRedirect = false;
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
//Returns "MovedPermanently", not 301 which is what I want.
int i_goodResponse = (int)response.StatusCode;
string s_goodResponse = response.StatusCode.ToString();
Console.WriteLine("Normal Response: " + i_goodResponse + " " + s_goodResponse);
Console.ReadLine();
}
catch (WebException we)
{
int i_badResponse = (int)((HttpWebResponse)we.Response).StatusCode;
string s_badResponse = ((HttpWebResponse)we.Response).StatusCode.ToString();
Console.WriteLine("Error Response: " + i_badResponse + " " + s_badResponse);
Console.ReadLine();
}
}
我发现的一些可能的代码:
void StartWebRequest()
{
HttpWebRequest webRequest = ...;
webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), webRequest);
}
void FinishWebRequest(IAsyncResult result)
{
HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}
最佳答案
这实际上是利用 Task Parallel Library 的好地方在.NET 4.0 中。我已将您的代码包装在一个 Parallel.For
block 中,该 block 将并行执行多组请求,整理每个并行分支中的总时间,然后计算总体结果。
int n = 16;
int reqs = 10;
var totalTimes = new long[n];
Parallel.For(0, n, i =>
{
for (int req = 0; req < reqs; req++)
{
Stopwatch w = new Stopwatch();
try
{
w.Start();
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://localhost:42838/Default.aspx");
webRequest.AllowAutoRedirect = false;
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
w.Stop();
totalTimes[i] += w.ElapsedMilliseconds;
//Returns "MovedPermanently", not 301 which is what I want.
int i_goodResponse = (int)response.StatusCode;
string s_goodResponse = response.StatusCode.ToString();
Console.WriteLine("Normal Response: " + i_goodResponse + " " + s_goodResponse);
}
catch (WebException we)
{
w.Stop();
totalTimes[i] += w.ElapsedMilliseconds;
int i_badResponse = (int)((HttpWebResponse)we.Response).StatusCode;
string s_badResponse = ((HttpWebResponse)we.Response).StatusCode.ToString();
Console.WriteLine("Error Response: " + i_badResponse + " " + s_badResponse);
}
}
});
var grandTotalTime = totalTimes.Sum();
var reqsPerSec = (double)(n * reqs * 1000) / (double)grandTotalTime;
Console.WriteLine("Requests per second: {0}", reqsPerSec);
TPL 在这里非常有用,因为它抽象了在进程中创建多个执行线程以及在这些线程上运行每个并行分支的细节。
请注意,这里您仍然需要小心 - 我们无法共享在线程之间的任务期间更新的状态,因此 totalTimes
的数组会整理每个并行分支的总数,并且仅求和一旦并行执行完成,就在最后结束。如果我们不这样做,我们就会面临竞争条件的可能性 - 两个单独的线程尝试同时更新总计数,可能会破坏结果。
我希望这是有意义的,并且对您来说是有用的(我在这里只计算每秒的请求数,其他统计数据应该相对容易添加)。如果您需要进一步说明,请添加评论。
关于c# - 如何发出并行 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5523854/