Получение "основного соединения было закрыто" по HttpWebRequest

У меня есть приложение, написанное на VB.NET (НЕ asp.net, это приложение Windows Console). Я пытаюсь вызвать URL (HTML-страницу) и получить ответ в виде строки. Ответ прямой JSON, никаких HTML-тегов. Открывается с { и закрывается с },

Я прекрасно создаю объект HttpWebRequest. Тогда позвони req.GetResponse(), Как только я это делаю, я получаю ошибку The underlying connection was closed: The connection was closed unexpectedly. Я гуглил и проверял стекопоток, и перепробовал все, что мне удалось найти (во многом это связано с конфигурациями служб WCF, которые не применяются).

Вот мой код:

Public Function GetJSON(ByRef d As db.Device) As Boolean
    Try
        d.Url = "http://" & d.IpAddress & ini.doc.<svc>.<url>.Value

        Dim req As HttpWebRequest = HttpWebRequest.Create(d.Url)
        // req.Accept = "*/*"
        // req.Timeout = 30000
        // req.ReadWriteTimeout = 30000
        // req.KeepAlive = False
        // req.UseDefaultCredentials = True
        // req.CachePolicy = HttpWebRequest.DefaultCachePolicy
        // req.Proxy = HttpWebRequest.DefaultWebProxy
        // req.ProtocolVersion = New System.Version(1, 0)

        Dim rsp As HttpWebResponse = req.GetResponse()

        Return True
    Catch ex As Exception
        Log(ex.Message)
        Return False
    Finally
        rsp = Nothing
        req = Nothing
    End Try
End Function

Закомментированные строки (неправильный стиль комментария, но поэтому SO будет правильно его анализировать) - это все, что я до сих пор пробовал, основываясь на том, что я нашел в Интернете. Никто из них не исправил это. Я проверил, что созданный URL-адрес правильный; если я вызываю точно такой же URL в моем браузере, он возвращает точно правильный ожидаемый ответ.

Я попытался использовать это, и я вижу фактические ожидаемые полные данные, возвращаемые в выводе акулы, затем несколько строк, а затем красная линия, которая говорит: http > 51943 [RST] Seq=1607 Win=0 Len=0 которая является последней строкой, отображаемой перед тем, как.NET выдает ошибку.

Я тоже пытался включить System.Net отслеживание / ведение журнала для каждого сообщения здесь, на SO, и в выходном файле, который я вижу аналогичным образом, все ожидаемые данные JSON возвращаются, но после их возвращения он выдает следующие строки в журнале трассировки.NET:

System.Net.Sockets Verbose: 0 : [7040] Exiting Socket#60467532::Receive()   -> 1605#1605
System.Net.Sockets Verbose: 0 : [7040] Socket#60467532::Receive()
System.Net.Sockets Verbose: 0 : [7040] Data from Socket#60467532::Receive
System.Net.Sockets Verbose: 0 : [7040] 00000000 :                                                 : 
System.Net.Sockets Verbose: 0 : [7040] Exiting Socket#60467532::Receive()   -> 0#0
System.Net.Sockets Verbose: 0 : [7040] Socket#60467532::Dispose()
System.Net Error: 0 : [7040] Exception in the HttpWebRequest#27806816:: - The underlying connection was closed: The connection was closed unexpectedly.
System.Net Error: 0 : [7040] Exception in the HttpWebRequest#27806816::GetResponse - The underlying connection was closed: The connection was closed unexpectedly.

Любые идеи, куда идти дальше, чтобы попытаться выяснить это? Мы читаем эти данные с некоторых сенсорных устройств мониторинга окружающей среды, и они дали нам этот URL для использования.

Две вещи, которые действительно меня заводят и смущают, это то, что
а) прекрасно работает при вызове в браузере
б) и WireShark, и трассировка.NET показывают, что все данные действительно возвращаются, и инфраструктура по какой-то причине исключает ПОСЛЕ получения всех данных!

Само по себе WebException очень мало используется, так как его InnerException имеет значение null, а его Status просто говорит "ConnectionClosed {8}"

Заранее спасибо!!!

ОБНОВЛЕНИЕ 08/18 1130: я также попытался теперь, используя только System.Net.WebRequest в отличие от HttpWebRequest, Это тоже не имело никакого значения.

ОБНОВЛЕНИЕ 08/18 1222: я просто попытался переключить свой код вместо использования [Http]Web[Request|Response] чтобы затемнить WebClient объект вместо этого и используя его DownloadString() метод. Это, однако, также вызывает ту же ошибку.

ОБНОВЛЕНИЕ 08/18 1230: пробовал с помощью My.Computer.Network.DownloadFile() - также получает ту же ошибку соединения закрыто.

6 ответов

Решение

Можете ли вы опубликовать все содержимое журнала трассировки на pastebin.com и разместить ссылку здесь?

Возможно, вы получаете это исключение, потому что в заголовке "Content-Length" сервер может сказать, что он отправляет N байтов сущности, но фактически отправляет меньше N байтов и закрывает соединение.

Ответ:

Спасибо за данные. Из трассировки и трассировки проволоки видно, что сервер не отправляет заголовки ответа, а напрямую отправляет данные. Это нарушение протокола HTTP. Вот почему клиент выбрасывает исключение.

Это помогает мне. Надеюсь, это кому-то тоже поможет.

Сразу после создания объекта HttpWebRequest добавьте эту строку.

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;

Это означает, что в качестве протокола безопасности указывается Secure Socket Layer (SSL) 3.0.

http://support.microsoft.com/kb/915599

Вот как у меня это получилось... Спасибо feroze за то, что указал мне правильное направление!
(начисленные баллы)

Public Function GetJSON(ByRef d As db.Device) As Boolean
    Try
        Dim tcp = New TcpClient()
        tcp.Connect(d.IpAddress, 80)

        Dim ns = tcp.GetStream()

        Dim req As Byte() = System.Text.Encoding.ASCII.GetBytes(
            "GET /getdata.htm HTTP/1.1" & vbCrLf & vbCrLf
        )
        ns.Write(req, 0, req.Length)

        Dim rsp(2048) As Byte, rcv As Integer
        Do
            rcv = ns.Read(rsp, 0, rsp.Length)
            d.JSON &= System.Text.Encoding.ASCII.GetString(rsp, 0, rcv)
        Loop Until rcv = 0

        tcp.Close()

        Return True
    Catch ex As Exception
        Log(ex.Message)
        Return False
    End Try
End Function

У меня была такая же проблема, касающаяся запроса без тела. В моем случае настройка ContentLength до нуля исправили проблему.

Проверьте задержку запроса. Если это больше, чем несколько мс, то стоит отключить алгоритм Nagle

 ServicePointManager.UseNagleAlgorithm = false;

В моем случае проблема заключалась в том, что мы использовали "http://.." в качестве адреса службы вместо "https://"...

Другие вопросы по тегам