如何连接,但等待使用HttpWebRequest发送任何标头?

时间:2014-04-28 14:49:40

标签: c# vb.net ssl web httpwebrequest

我想发一个https请求但是我想先发起连接而不发送标题,甚至是GET /something/ HTTP/1.1部分。换句话说,我想保持连接准备就绪,并在我完成后立即发送所有内容。

我本可以使用简单的TCP / IP完成此操作,但目前我正在使用some issues with it

我已尝试过SendChunked属性,但它只发送要发布的数据块。

编辑:为了更清楚,我想要的是:

  • 连接到IP
  • 创建SSL流和AuthenticateAsClient
  • 等待信号
  • 现在发送网络请求

我练习了等待部分,因此无需对其进行详细解释。

2 个答案:

答案 0 :(得分:4)

简答

HttpWebRequest没有公开任何接口以允许在发出请求之前预热连接。

动机

有人想要这样做的原因是因为打开TCP连接需要发起者在发送任何数据之前等待一个RTT,因为HTTPS可能需要另一个RTT等待执行密钥交换。

如果你有一个从客户端到数据中心的RTT为50毫秒,那么像这样预热连接可能会减少从125毫秒发送一个简单请求所需的时间(2.5 RTT发送请求,但不是得到响应)到25毫秒(0.5 RTT发送请求,但没有得到响应)。这减少了80%。

替代解决方案

可以在不编写自己的Http客户端或使用HttpWebRequest之外的其他东西的情况下实现一些减少,但在某些情况下,它必须等待。

一般技术是依靠HTTP 1.1重用连接(也称为keep-alive)来通过现有的TCP套接字/ SSL会话发送请求。

先决条件:您需要知道您正在呼叫的Web服务器的保持活动间隔。 60秒是非常典型的,但不要假设它,用Fiddler观察它或检查服务器和负载均衡器上的设置(如果你有权访问它们)。

让我们说保持活动间隔为60秒。创建一个HttpWebRequest并向" ping"发送一个请求。 url(即使是不存在的文件......除非服务器配置错误,否则连接仍应关闭404响应)。在小于保持活动间隔的某个间隔(例如,每55秒)再次重新发送请求。当您想要向服务器发送请求时,您需要等待锁定您拥有的单个HttpWebRequest。当锁无法等待时,您的请求通常会立即通过现有的TCP套接字和SSL会话。在罕见的情况下,HttpWebRequest被锁定,你必须等待最多1个RTT才能被释放(平均而言,你等待0.5个RTT,当它被锁定时,这是罕见的,因为有可能请求已经在线路上发送,并且响应可能已经在线路上了。)

此解决方案可以保证套接字将保持活动状态,但它可以很好地工作。

不要嗤之以鼻,但如果性能如此重要,那么您可能不应该使用HTTP和/或担心编写或使用非HttpWebRequest客户端。

答案 1 :(得分:2)

我看了一下你关于WebClient和TcpClient之间性能的另一篇文章。我想确保我对这篇文章的回答与你在其他帖子中尝试过的内容一致。我想给出的答案是使用TcpClient,但在你的其他帖子中你发现它很慢。我编写了相同的测试但是我得到了不同的结果。在我的测试中,TcpClient平均比WebClient快10ms。

使用WebClient

Stopwatch sw = new Stopwatch();
sw.Start();

using (WebClient client = new WebClient())
{
    string response = client.DownloadString("https://www.google.com");
}

sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

使用TcpClient

Stopwatch sw = new Stopwatch();
sw.Start();

using (TcpClient client = new TcpClient("www.google.com", 443))
using (SslStream stream = new SslStream(client.GetStream(), true))
{

    stream.AuthenticateAsClient("www.google.com");

    using (StreamWriter writer = new StreamWriter(stream))
    using (StreamReader reader = new StreamReader(stream))
    {
        writer.AutoFlush = true;

        // Wait for your signal here


        writer.Write("GET /\r\n");

        string response = reader.ReadToEnd();
    }
}

sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

您需要使用TcpClient类来完成您想要的操作。 HttpWebRequest不提供底层流和连接所需的级别访问。

使用TcpClient,您可以在发送" GET /"之前等待您的信号。