C # - Соединение: заголовок keep-alive не отправляется во время HttpWebRequest - PullRequest
28 голосов
/ 18 сентября 2011

Я пытаюсь отправить, чтобы отправить следующий заголовок с моим HttpWebRequest:

Connection: keep-alive

Однако заголовок никогда не отправляется. Fiddler2 показывает, что всякий раз, когда я запрашиваю страницу в Google Chrome, отправляется заголовок. Однако мое приложение по какой-то причине отказывается отправлять этот заголовок.

Я установил для свойства KeepAlive значение true (по умолчанию оно равно true), однако заголовок по-прежнему не отправляется.

Я пытаюсь отправить этот заголовок с несколькими запросами HttpWeb, но все они в основном выглядят так:

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

Кто-нибудь знает, что я должен сделать, чтобы этот заголовок был отправлен?

Fiddler2 Raw от 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 из моего приложения:

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.

Ответы [ 5 ]

36 голосов
/ 28 сентября 2011

У меня была такая же проблема: заголовок Connection: Keep-Alive не отправляется, кроме первого запроса, и сервер, к которому я обращался, не даст мне правильный ответ, если он отсутствует. Итак, вот мои обходные пути к этой проблеме:

Сначала устанавливается свойство ProtocolVersion экземпляра HttpWebRequest на HttpVersion.Version10. За исключением того, что команда http станет GET xxx HTTP/1.0, она работает и использует только общедоступный API.

Второй способ использует отражение для изменения внутреннего свойства ServicePoint.HttpBehaviour экземпляра HttpWebRequest, например:

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

Надеюсь, это поможет.

8 голосов
/ 09 декабря 2012

Я боролся с этой проблемой уже полдня!И дорогой старый Fiddler (мой ангел-хранитель) был непреднамеренно частью проблемы:

Всякий раз, когда я проверял свои HTTP POST, используя Fiddler, включенный мониторинг - проблема НЕ появлялась всякий раз, когда я проверял мои HTTP POST с отключенным мониторингом Fiddler -проблема DID появляется

Мои сообщения были отправлены с протоколом 1.1 и Keep-Alive был проигнорирован / избыточен / почему после первоначального подключения.то есть я мог видеть это в заголовке первого POST (через Fiddler!), но не в последующих POST, несмотря на использование того же кода.Эй, хо ...

Но удаленный сервер будет отвечать только в случае отправки сообщения Keep-Alive.Теперь я не могу доказать это, но я подозреваю, что Fiddler, отслеживающий соединение, заставил удаленный сервер думать или полагать, что соединение все еще было активным (несмотря на то, что Keep-Alives не отправлялось после моего первого POST) и отвечало правильно.Как я уже сказал, во второй раз, когда я выключил Fiddler, отсутствие Keep-Alives вызвало тайм-аут удаленного сервера для меня ..

Я реализовал решение 1.0, описанное выше, и мои POSTS теперь работают, с или без Fiddlerвкл или выкл.Надеюсь, это поможет кому-то еще застрявшему где-то ...

7 голосов
/ 18 сентября 2011

Вы делаете это правильно.Код должен привести к добавлению следующего заголовка:

Connection: Keep-Alive

Отправьте код, который вы используете для отправки запроса и необработанного вывода из Fiddler, если вы не видите этот заголовок.Вы также можете игнорировать это, поскольку соединение HTTP 1.1 по умолчанию keep-alive .

Обновление: похоже, что .NET явно устанавливает Keep-Alive только для первого (!) Запроса.Дальнейшие запросы к тому же хосту / url не будут иметь этот заголовок, предположительно, потому что базовое соединение tcp уже используется повторно.

3 голосов
/ 10 ноября 2014

Я знаю ответ на этот вопрос, поскольку у меня возникла та же проблема, и мне удалось ее решить, унаследовав веб-клиента и переопределив его метод 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;
    }
}

Как видите, я не только включаю поддержку активности, но и использую файлы cookie и другие заголовки!

Надеюсь, это поможет!

Киран

2 голосов
/ 13 августа 2012

После загрузки 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}
);
...