C# - 连接:在 HttpWebRequest 期间未发送 keep-alive 标头

发布于 2024-12-04 21:19:25 字数 3279 浏览 1 评论 0原文

我正在尝试使用 HttpWebRequest 发送以下标头:

Connection: keep-alive

但是,标头从未发送。 Fiddler2 显示,每当我在 Google Chrome 中请求页面时,都会发送标头。但是,我的应用程序由于某种原因拒绝发送此标头。

我已将 KeepAlive 属性设置为 true(无论如何默认情况下都是 true),但标头仍然没有发送。

我正在尝试使用多个 HttpWebRequest 发送此标头,但它们基本上都是这样的:

HttpWebRequest logIn6 = (HttpWebRequest)WebRequest.Create(new Uri(responseFromLogIn5));
logIn6.CookieContainer = cookies;
logIn6.KeepAlive = true;
logIn6.Referer = "https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/";
logIn6.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1";
logIn6.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
logIn6.Headers.Add("Accept-Encoding:gzip,deflate,sdch");
logIn6.Headers.Add("Accept-Language:en-US,en;q=0.8");
logIn6.Headers.Add("Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3");
logIn6.AllowAutoRedirect = false;

HttpWebResponse logIn6Response = (HttpWebResponse)logIn6.GetResponse();
string responseFromLogIn6 = logIn6Response.GetResponseHeader("Location");

cookies.Add(logIn6Response.Cookies);

logIn6Response.Close();

有谁知道我必须做什么才能确保发送此标头?

来自 Chrome 的 Fiddler2 Raw:

GET xxx HTTP/1.1
Host: accounts.google.com
Connection: keep-alive
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: xxx

HTTP/1.1 302 Moved Temporarily
Set-Cookie: xxx
Set-Cookie: xxx
Location: xxx
Content-Type: text/html; charset=UTF-8
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Date: Sat, 17 Sep 2011 22:27:09 GMT
Expires: Sat, 17 Sep 2011 22:27:09 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 2176
Server: GSE

来自我的应用程序的 Fiddler2 Raw:

GET xxx HTTP/1.1
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Host: accounts.google.com

HTTP/1.1 302 Moved Temporarily
Location: xxx
Content-Type: text/html; charset=UTF-8
Date: Sun, 18 Sep 2011 00:05:40 GMT
Expires: Sun, 18 Sep 2011 00:05:40 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 573
Server: GSE

我试图让第二个 Fiddler2 原始信息看起来像第一个 Fiddler2 原始信息。

I'm trying to send to send the following header with my HttpWebRequest:

Connection: keep-alive

However, the header is never sent. Fiddler2 is showing that whenever I request the page in Google Chrome, the header is sent. However, my application refuses to send this header for some reason.

I have set the KeepAlive property to true (it's true by default anyway), yet the header still does not get sent.

I am trying to send this header with multiple HttpWebRequests, but they all basically look like this:

HttpWebRequest logIn6 = (HttpWebRequest)WebRequest.Create(new Uri(responseFromLogIn5));
logIn6.CookieContainer = cookies;
logIn6.KeepAlive = true;
logIn6.Referer = "https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/";
logIn6.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1";
logIn6.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
logIn6.Headers.Add("Accept-Encoding:gzip,deflate,sdch");
logIn6.Headers.Add("Accept-Language:en-US,en;q=0.8");
logIn6.Headers.Add("Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3");
logIn6.AllowAutoRedirect = false;

HttpWebResponse logIn6Response = (HttpWebResponse)logIn6.GetResponse();
string responseFromLogIn6 = logIn6Response.GetResponseHeader("Location");

cookies.Add(logIn6Response.Cookies);

logIn6Response.Close();

Does anyone know what I have to do to make sure this header is sent?

Fiddler2 Raw From Chrome:

GET xxx HTTP/1.1
Host: accounts.google.com
Connection: keep-alive
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: xxx

HTTP/1.1 302 Moved Temporarily
Set-Cookie: xxx
Set-Cookie: xxx
Location: xxx
Content-Type: text/html; charset=UTF-8
P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
Date: Sat, 17 Sep 2011 22:27:09 GMT
Expires: Sat, 17 Sep 2011 22:27:09 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 2176
Server: GSE

Fiddler2 Raw From My Application:

GET xxx HTTP/1.1
Referer: https://login.yahoo.com/config/login?.src=spt&.intl=us&.lang=en-US&.done=http://football.fantasysports.yahoo.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Host: accounts.google.com

HTTP/1.1 302 Moved Temporarily
Location: xxx
Content-Type: text/html; charset=UTF-8
Date: Sun, 18 Sep 2011 00:05:40 GMT
Expires: Sun, 18 Sep 2011 00:05:40 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 573
Server: GSE

I'm trying to get the second Fiddler2 raw information to look like the first Fiddler2 raw information.

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

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

发布评论

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

评论(5

夜访吸血鬼 2024-12-11 21:19:25

我遇到了同样的问题:除了第一个请求之外,Connection: Keep-Alive 标头不会发送,并且如果缺少该标头,我访问的服务器将不会给我正确的响应。因此,这是我解决此问题的方法:

首先将 HttpWebRequest 实例的 ProtocolVersion 属性设置为 HttpVersion.Version10。除了 http 命令将变为 GET xxx HTTP/1.0 之外,它仅工作并使用公共 API。

第二种方式使用反射来修改 HttpWebRequest 实例的内部属性 ServicePoint.HttpBehaviour,如下所示:

var req = (HttpWebRequest)WebRequest.Create(someUrl);

var sp = req.ServicePoint;
var prop = sp.GetType().GetProperty("HttpBehaviour", 
                        BindingFlags.Instance | BindingFlags.NonPublic);
prop.SetValue(sp, (byte)0, null);

req.GetResponse().Close();

希望这会有所帮助。

I've had the same issue: The Connection: Keep-Alive header is not sent except the first request, and the server I accessed won't give me the correct response if it is missing. So, here are my workarounds to this issue:

First is set the ProtocolVersion property of HttpWebRequest instance to HttpVersion.Version10. Except the http command will become GET xxx HTTP/1.0, it works and uses only the public API.

The second way uses the reflection to modify the internal property ServicePoint.HttpBehaviour of HttpWebRequest instance, like this:

var req = (HttpWebRequest)WebRequest.Create(someUrl);

var sp = req.ServicePoint;
var prop = sp.GetType().GetProperty("HttpBehaviour", 
                        BindingFlags.Instance | BindingFlags.NonPublic);
prop.SetValue(sp, (byte)0, null);

req.GetResponse().Close();

Hope this helps.

你的笑 2024-12-11 21:19:25

这个问题困扰了我半天!亲爱的老 Fiddler(我的守护天使)无意中成为了问题的一部分:

每当我使用 Fiddler 监控功能测试我的 HTTP POST 时,问题就没有出现
每当我在 Fiddler 监控关闭的情况下测试我的 HTTP POST 时,都会出现问题:

我的 POSTS 是使用协议 1.1 发送的,并且在初始连接后,Keep-Alive 被忽略/冗余/为什么。即我可以在第一个 POST 的标题中看到它(通过 Fiddler!),但在后续的 POST 中看不到它,尽管使用相同的代码。嘿嘿...

但是远程服务器只有在发送 Keep-Alive 消息时才会响应。现在我无法证明这一点,但我怀疑 Fiddler 监视连接导致远程服务器认为或相信连接仍然处于活动状态(尽管在我的第一次 POST 后没有发送 Keep-Alives)并正确响应。正如我所说,在我关闭 Fiddler 的那一刻,Keep-Alives 的缺失导致远程服务器超时。

我实现了上述 1.0 解决方案,无论 Fiddler 打开或关闭,我的帖子现在都可以工作。希望这可以帮助其他陷入困境的人......

I struggled with this problem for half a day! And dear old Fiddler (my guardian angel) was inadvertantly part of the problem:

Whenever I tested my HTTP POSTs using Fiddler monitoring ON - the problem DIDN'T appear
Whenever I tested my HTTP POSTs with Fiddler monitoring OFF - the problem DID appear

My POSTS were sent with protocol 1.1 and the Keep-Alive was ignored/redundant/why after the initial connection. i.e. I could see it in the header of the first POST (via Fiddler!), but not in subsequent POSTs despite using the same code. Hey ho ...

But the remote server would only respond if Keep-Alive was sent. Now I can't prove this, but I suspect that Fiddler monitoring the connection caused the remote server to think or believe that the connection was still active (despite no Keep-Alives sent after my first POST) and responded correctly. As I said, the second I turned Fiddler off, the absence of Keep-Alives caused the remote server to timeout on me..

I implemented the 1.0 solution described above and my POSTS now work, with or without Fiddler on or off. Hope this helps somebody else stuck somewhere ...

怎樣才叫好 2024-12-11 21:19:25

你做得对。该代码应导致添加以下标头:

Connection: Keep-Alive

如果您没有看到此标头,请发布用于从 Fiddler 发送请求和原始输出的代码。您也可以忽略这一点,因为 HTTP 1.1 连接默认情况下保持活动状态。

更新:看起来 .NET 只为第一个(!)请求显式设置 Keep-Alive。对同一主机/url 的进一步请求将不会有此标头,大概是因为底层 tcp 连接已被重用。

You doing it right. The code should result in following header added:

Connection: Keep-Alive

Post the code that you use for sending request and Raw output from Fiddler if you don't see this header. You may also ignore this because HTTP 1.1 connection is keep-alive by default.

Update: it looks like .NET only sets Keep-Alive explicitly for the first (!) request. Further requests to the same host/url will not have this header presumably because underlying tcp connection is already being reused.

我还不会笑 2024-12-11 21:19:25

下载 HttpWebRequest 源代码后,注意到每个属性都会检查 HeaderCollection 的一些已知标头。为了摆脱这种情况,对该集合进行一些反思,使其发挥作用

var webRequest = (HttpWebRequest) WebRequest.Create(url);
webRequest.Headers.GetType().InvokeMember("ChangeInternal",
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
    Type.DefaultBinder, webRequest.Headers, new object[] {name, value}
);

After downloading HttpWebRequest source code, noticed that every property checks some known headers for HeaderCollection. To get rid of that doing some reflection stuff on that collection make it work

var webRequest = (HttpWebRequest) WebRequest.Create(url);
webRequest.Headers.GetType().InvokeMember("ChangeInternal",
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
    Type.DefaultBinder, webRequest.Headers, new object[] {name, value}
);
南薇 2024-12-11 21:19:25

我知道这个问题的答案,因为我遇到了同样的问题,并设法通过继承 webclient 并覆盖它的 Get Web Request 方法来解决它。

请参阅下面的代码:

    public class CookieAwareWebClient : WebClient
{
    public CookieContainer CookieContainer { get; set; }

    public CookieAwareWebClient()
        : this(new CookieContainer())
    { }

    public CookieAwareWebClient(CookieContainer c)
    {
        this.CookieContainer = c;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        var castRequest = request as HttpWebRequest;

        if (castRequest != null)
        {
            castRequest.KeepAlive = true; //<-- this what you want! The rest you don't need. 
            castRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
            castRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36";
            castRequest.Referer = "https://www.jobserve.com/gb/en/Candidate/Login.aspx?url=48BB4C724EA6A1F2CADF4243A0D73C13225717A29AE8DAD6913D";
            castRequest.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
            castRequest.Headers.Add("Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6");
            castRequest.CookieContainer = this.CookieContainer;
        }

        return request;
    }
}

如您所见,我不仅启用了 keep-alive,而且还利用了 cookie 和其他标头!

我希望这有帮助!

基兰

I know the answer for this as I had the same problem and managed to solve it by inheriting the webclient and overriding it's Get Web Request method.

See the code below:

    public class CookieAwareWebClient : WebClient
{
    public CookieContainer CookieContainer { get; set; }

    public CookieAwareWebClient()
        : this(new CookieContainer())
    { }

    public CookieAwareWebClient(CookieContainer c)
    {
        this.CookieContainer = c;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        var castRequest = request as HttpWebRequest;

        if (castRequest != null)
        {
            castRequest.KeepAlive = true; //<-- this what you want! The rest you don't need. 
            castRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
            castRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36";
            castRequest.Referer = "https://www.jobserve.com/gb/en/Candidate/Login.aspx?url=48BB4C724EA6A1F2CADF4243A0D73C13225717A29AE8DAD6913D";
            castRequest.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
            castRequest.Headers.Add("Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6");
            castRequest.CookieContainer = this.CookieContainer;
        }

        return request;
    }
}

As you can see I am not only enabling keep-alive but I am utilizing cookies and other headers also!

I hope that helps!

Kiran

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