Получение "основного соединения было закрыто" по 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.
Вот как у меня это получилось... Спасибо 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://"...