C# – 连接:在HttpWebRequest期间未发送保持活动标头

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

Connection: keep-alive

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

我已将KeepAlive属性设置为true (默认情况下默认为true ),但标题仍未发送。

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

 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原始信息。

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

首先将HttpWebRequest实例的ProtocolVersion属性设置为HttpVersion.Version10 。 除了http命令将成为GET xxx HTTP/1.0 ,它只能使用公共API。

第二种方法使用reflection来修改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(); 

希望这可以帮助。

我在这个问题上挣扎了半天! 亲爱的老提琴手(我的守护天使)无意中成了问题的一部分:

每当我使用Fiddler监控ON测试我的HTTP POST时 – 问题DID NOT不出现每当我用Fiddler监控OFF测试我的HTTP POST时 – 出现问题DID

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

但远程服务器只会在发送Keep-Alive时响应。 现在我无法certificate这一点,但我怀疑Fiddler监控连接导致远程服务器认为或认为连接仍处于活动状态(尽管在我的第一次POST后没有发送Keep-Alives)并且正确响应。 就像我说的那样,第二次我把Fiddler关掉,没有Keep-Alives导致远程服务器超时了。

我实现了上面描述的1.0解决方案,我的POSTS现在可以工作,无论是否打开Fiddler。 希望这有助于其他人卡在某处……

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

 Connection: Keep-Alive 

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

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

下载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} ); 

我知道答案,因为我遇到了同样的问题并设法通过inheritancewebclient并覆盖它的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; } } 

正如你所看到的,我不仅能够保持活着,而且我还在使用cookies和其他标题!

我希望有所帮助!

基兰