【问题标题】:Why does sending post data with WebRequest take so long?为什么用 WebRequest 发送 post 数据需要这么长时间?
【发布时间】:2010-04-22 11:26:08
【问题描述】:

我目前正在创建一个 C# 应用程序以连接到 php / MySQL 在线系统。应用程序需要将发布数据发送到脚本并获得响应。

当我发送以下数据时

用户名=测试&密码=测试

我收到以下回复...

在 22/04/2010 12:15:42 开始请求 完成创建请求:花费 00:00:00.0570057 在 22/04/2010 12:15:42 传输数据 传输数据:取 00:00:06.9316931

正如您所看到的,将数据实际发送到脚本需要 6 秒,我已经完成了进一步的测试,再见从 telnet 发送数据,并通过将本地文件中的 post 数据发送到 url,他们甚至不需要一秒钟所以这不是网站上托管脚本的问题。

如果是两个简单的字符串,为什么传输数据需要 6 秒?

我使用自定义类来发送数据

class httppostdata
{
    WebRequest request;
    WebResponse response;

    public string senddata(string url, string postdata)
    {
        var start = DateTime.Now;
        Console.WriteLine("Starting request at " + start.ToString());

        // create the request to the url passed in the paramaters
        request = (WebRequest)WebRequest.Create(url);


        // set the method to post
        request.Method = "POST";
        // set the content type and the content length
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = postdata.Length;
        // convert the post data into a byte array
        byte[] byteData = Encoding.UTF8.GetBytes(postdata);
        var end1 = DateTime.Now;
        Console.WriteLine("Finished creating request : took " + (end1 - start));

        var start2 = DateTime.Now;
        Console.WriteLine("Transmitting data at " + start2.ToString());
        // get the request stream and write the data to it
        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteData, 0, byteData.Length);
        dataStream.Close();
        var end2 = DateTime.Now;
        Console.WriteLine("Transmitted the data : took " + (end2 - start2));


        // get the response
        var start3 = DateTime.Now;
        Console.WriteLine("Getting the response at " + start3.ToString());


        response = request.GetResponse();
        //Console.WriteLine(((WebResponse)response).StatusDescription);
        dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        var end3 = DateTime.Now;
        Console.WriteLine("Getting response " + (end3 - start3));

        // read the response
        string serverresponse = reader.ReadToEnd();
        var end3a = DateTime.Now;
        Console.WriteLine("Finished response " + (end3a - start3));

        Console.WriteLine("Entire call took " + (end3a - start));

        //Console.WriteLine(serverresponse);
        reader.Close();
        dataStream.Close();
        response.Close();

        return serverresponse;
    }
}

我用它来称呼它

private void btnLogin_Click(object sender, EventArgs e)
{
    // string postdata;

    if (txtUsername.Text.Length < 3 || txtPassword.Text.Length < 3)
    {
        MessageBox.Show("Missing your username or password.");
    }
    else
    {
        string postdata = "username=" + txtUsername.Text +
                          "&password=" + txtPassword.Text;

        httppostdata myPost = new httppostdata();
        string response = myPost.senddata("http://www.domainname.com/scriptname.php", postdata);
        MessageBox.Show(response);
    }
}

【问题讨论】:

  • 我知道在您的示例中它是 http,但在您的实际六秒测试场景中是 URL https?由于握手、检查 CRL、调用 OCSP 等可能会产生开销。

标签: c# webrequest webresponse


【解决方案1】:

确保将 WebRequest 的代理属性显式设置为 null,否则它将尝试自动检测代理设置,这可能需要一些时间。

【讨论】:

  • 如果是代理的情况,我会更好地加载启动画面并进行空白呼叫吗?我问的原因是因为该软件正在笔记本电脑的多个网络上使用,并且某些网络使用代理
【解决方案2】:

很有可能,因为在您的测试中,您只调用了一次,您看到的延迟是正在 JIT 编译的 C# 代码。

更好的测试是调用两次,然后丢弃第一次的时间,看看它们是否更好。

更好的测试是放弃第一组计时,然后运行多次并取平均值,尽管对于非常松散的“指示性”视图,这可能没有必要。

顺便说一句,对于这种时机,您最好使用System.Diagnostics.Stopwatch 类而不是System.DateTime

[编辑] 另外,请注意 Mant101 关于代理的建议,如果设置无代理无法解决问题,您可能希望设置 Fiddler 并设置您的请求以使用 Fiddler 作为其代理。这将允许您拦截实际的 http 调用,以便您可以从框架外部更好地分解 http 调用时间本身。

【讨论】:

  • 这是大错特错。 (1) 方法在运行前是JIT编译的,不是中途编译的。 (2) JIT 编译这么短的方法不需要 6 秒。 (3) 与 6 秒相比,获得计时所需的时间微不足道。 (4) 当你测量需要几毫秒的短时间、时间关键的操作时,你会取平均值;与 HTTP 服务器通信需要 6 秒时不会。 (5) 虽然 DateTime.Now 的准确度不如秒表准确,但在秒的范围内,准确度的差异完全可以忽略不计。
  • 1) 这个方法在运行之前可能会被 jitted,但是你会注意到它调用了其他方法。正是这些可以随着这个方法的进展而被jit。 2) JIT 所需的时间取决于许多因素,包括当前内存使用(以及需要换页)、磁盘速度等。通常它很快。总是?不。 3) 我从来没有说过不是 4) 我的意思是 - 如果这种缓慢的体验是由于磁盘 IO 之类的原因,平均可能有助于减少影响。我不是在谈论平均以消除时序抖动。你的假设,不是我的。 5) 我说的是“作为一般规则”。
  • 对第 4 点的补充 - 在您的措辞中暗示您认为 6 秒是由于与 HTTP 服务器通信。我建议它可能不是。您执行平均短时间关键操作,以减少时钟抖动和其他随机误差源的影响。您可以这样做,以减少您的计算机忙于执行在测试时不明显的其他任务对计算机的影响。可能值得一次又一次地运行相同的任务,可能在不同的时间,以消除隐藏的计划任务或其他任务的影响。
  • 感谢秒表的建议,我会调查一下,至于 JIT,并不是这样,因为我一个接一个地对同一个函数进行了多次调用,并且总是得到 5 秒以上的时间这里的系统是一个完全成熟的服务器,具有 6Gb 内存,用于开发
  • 是的 - 在这种情况下,您可能已经消除了 JITing 作为原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 2012-08-09
相关资源
最近更新 更多