6

Ho un'applicazione scritta in VB.NET (NON asp.net, è un'app di Console di Windows). Sto cercando di chiamare un URL (una pagina HTML) e recuperare la risposta in una stringa. La risposta è diretta JSON, nessun tag html qualunque. Si apre con { e si chiude con }.Ottenere "connessione sottostante chiusa" su HttpWebRequest

Ho creato l'oggetto HttpWebRequest fine. Quindi chiamare req.GetResponse(). Non appena faccio questo ottengo l'errore The underlying connection was closed: The connection was closed unexpectedly. Ho cercato su google e ho controllato StackOverflow, e ho provato tutto quello che ho trovato che si applica (molte cose hanno a che fare con le configurazioni del servizio WCF, che non si applicano).

Ecco il mio codice:

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 

Le linee commentate (commento stile sbagliato, ma così così sarà analizzarlo a destra) sono tutte le cose che ho provato così lontano basato su quello che ho trovato in rete . Nessuno di loro ha risolto il problema. Ho verificato che l'URL che si sta compilando sia corretto; se chiamo esattamente lo stesso URL nel mio browser restituisce esattamente la risposta attesa giusta.

ho provato wiresharking ... e vedo il attesi, dati effettivi completi tornano nell'output squalo, e poi un paio di righe, e poi una linea rossa che dice: http > 51943 [RST] Seq=1607 Win=0 Len=0 che è l'ultima riga mostrare prima che .NET stia generando l'errore.

Ho anche cercato di accendere System.Net tracciatura/registrazione per un post qui su SO, e nel file di output da quel che vedo allo stesso modo tutti i dati JSON attesi fa tornare, ma dopo si torna getta queste righe nel log di traccia .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. 

Qualche idea su dove andare per provare a capirlo? Stiamo leggendo questi dati da alcuni sensori di monitoraggio ambientale e ci hanno dato questo URL da utilizzare.

Due cose che mi ha veramente ottenere e mi confondono su questo sono che
a) funziona perfettamente bene quando viene chiamato in un browser
b) sia WireShark e .NET tracing mostra tutti i dati effettivamente IS tornare indietro e il framework è per qualche motivo tranne che dopo aver ricevuto tutti i dati!

Il WebException stesso è stato molto poco, come il suo InnerException è nullo e il suo status dice solo "ConnectionClosed {8}"

Grazie in anticipo !!!

UPDATE 08/18 1130: Inoltre ho provato ora utilizzando solo System.Net.WebRequest al contrario di HttpWebRequest. Questo non ha fatto alcuna differenza neanche.

UPDATE 08/18 1222: Ho appena provato commutazione mio codice invece di utilizzare [Http]Web[Request|Response] ad oscuramento un oggetto WebClient invece e utilizzando il metodo DownloadString(). Questo tuttavia anche genera lo stesso errore esatto.

AGGIORNAMENTO 08/18 1230: Provato usando My.Computer.Network.DownloadFile() - ottiene anche lo stesso errore di connessione chiusa.

+0

Ecco un pastebin della mia completa network.log traccia .NET file: http://pastebin.com/QfY05a11. Puoi vedere tutti i dati JSON che tornano sulla linea 41. – eidylon

+0

Ecco un pastebin del registro di traffico di Wireshark: http://pastebin.com/0hbEQerc. Puoi vedere i dati tornare sulla linea 607. – eidylon

risposta

4

È possibile pubblicare l'intero contenuto del registro di traccia su pastebin.com e pubblicare un collegamento qui?

Si potrebbe ottenere questa eccezione perché il server potrebbe dire nell'intestazione "Content-Length" che sta inviando N byte di entità, ma in realtà sta inviando meno di N byte e chiude la connessione.

Risposta:

Grazie per i dati. Dalla traccia tracelog e wireshark, sembra che il server non stia inviando alcuna intestazione di risposta e inviando direttamente i dati. Questa è una violazione del protocollo HTTP. Ecco perché il cliente lancia l'eccezione.

+0

Cool site ... mai visto prima. Pubblicherà quelli momentaneamente ... – eidylon

+0

Sì, dal tracelog posso vedere che il server non risponde con nessun header di risposta HTTP valido. Il server deve prima inviare le intestazioni di risposta HTTP e quindi inviare il payload JSON. Questo è il problema – feroze

+0

Inoltre c'è un bug nel tuo codice. Non si smaltisce l'oggetto HttpWebResponse ricevuto dalla chiamata a GetResponse(). È necessario chiamare Dispose() su quell'oggetto, altrimenti si esauriranno le connessioni al server. – feroze

2

Ecco come ho funzionato ... Grazie a feroze per avermi indicato nella giusta direzione!
(punti assegnati)

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 
+1

'tcp.Close()' dovrebbe essere chiamato dall'interno di "finally", altrimenti non verrà chiamato se c'è un'eccezione prima della chiamata '.Close()'. – sharptooth

+0

@sharptooth Buon punto. – eidylon

1

Questo mi aiuta. Spero che aiuti anche qualcuno.

Subito dopo aver creato l'oggetto HttpWebRequest, aggiungere questa riga.

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

Che cosa significa è specifica il Secure Socket Layer (SSL) 3.0 come protocollo di sicurezza

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

0

Controllare la latenza della richiesta. Se si tratta di più di un paio ms allora vale la pena disabilitando l'algoritmo Nagle

ServicePointManager.UseNagleAlgorithm = false; 
0

ho avuto lo stesso problema per quanto riguarda la richiesta senza un corpo. Nel mio caso, l'impostazione di ContentLength su ZERO ha risolto il problema.

0

Nel mio caso il problema era che abbiamo usato "http: // .." come indirizzo di servizio invece di "https: //" ...

Problemi correlati