如何发出并行 HTTP 请求

发布于 2024-10-28 23:28:50 字数 1777 浏览 3 评论 0原文

我有一个控制台应用程序,它向网页发出单个请求并返回其服务器状态,例如。 200、404 等。

我想应用以下更改:

用户输入列表:

  • 请求的 URL
  • 要使用多少个并行连接(并发用户)
  • 提交尽可能多的时间(秒)请求,因为它可以

输出列表:

  • 显示总获取次数
  • 显示每秒
  • 获取次数显示平均响应时间(毫秒)

我想最好的方法是并行运行多个 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;
}

I have a console app that makes a single request to a web page and returns its server status eg. 200, 404, etc..

I'd like to apply following changes:

List of User Inputs:

  • Url to request
  • How many parallel connections to use(concurrent users)
  • How long(seconds) to submit as many requests as it can

List of Outputs:

  • Show Total Fetches
  • Show Fetches per Second
  • Show Average Response Time (ms)

I imagine the best way to do it is to run multiple http fetches in parallel and run in a single process, so it doesn't bog down the client machine.

I really like C# but I'm still new to it. I've researched other articles about this but I don't fully understand them so any help would be greatly appreciated.

My Code:

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();
        }
    }

Some possible code that I found:

void StartWebRequest()
{
    HttpWebRequest webRequest = ...;
    webRequest.BeginGetResponse(new AsyncCallback(FinishWebRequest), webRequest);
}

void FinishWebRequest(IAsyncResult result)
{
    HttpWebResponse response = (result.AsyncState as HttpWebRequest).EndGetResponse(result) as HttpWebResponse;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相思故 2024-11-04 23:28:50

这实际上是使用任务并行库的好地方.NET 4.0。我已将您的代码包装在 Parallel.For 块中,该块将并行执行多组请求,整理每个并行分支中的总时间,然后计算总体结果。

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 的数组会整理每个并行分支的总数,并且仅在一旦并行执行完成,就结束了。如果我们不这样做,我们就会面临竞争条件的可能性 - 两个单独的线程尝试同时更新总计数,可能会破坏结果。

我希望这是有意义的,并且对您来说是有用的(我在这里只计算每秒的请求数,其他统计数据应该相对容易添加)。如果您需要进一步说明,请添加评论。

This is actually a good place to make use of the Task Parallel Library in .NET 4.0. I have wrapped your code in a Parallel.For block which will execute a number of sets of requests in parallel, collate the total times in each parallel branch, and then calculate the overall result afterwards.

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);

The TPL is very useful here, as it abstracts away the detail of creating multiple threads of exececution within your process, and running each parallel branch on these threads.

Note that you still have to be careful here - we cannot share state which is updated during the tasks between threads, hence the array for totalTimes which collates the totals for each parallel branch, and only summed up at the very end, once the parallel execution is complete. If we didn't do this, we are open to the possibility of a race condition - where two seperate threads attempt to update the total count simultaneously, potentially corrupting the result.

I hope this makes sense and is useful as a start for you (I only calculate requests per second here, the other stats should be relatively easy to add). Add comments if you need further clarifications.

陌路终见情 2024-11-04 23:28:50

您已经回答了自己的问题,您可以使用 BeginGetResponse 来启动异步请求。

如果您更熟悉事件然后使用 AsyncResult,另一种更方便的方法可能是使用 WebClient 类。

DownloadDataCompletedEventHandlerd

You have already answered your own question, you can use BeginGetResponse to start async request.

Another, and more convenient method might be using WebClient class, if you are more familiar with events then with AsyncResult.

DownloadDataCompletedEventHandlerd

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文