Visualizzazione dei risultati da 1 a 5 su 5

Discussione: [VB6] Winsock e HTTP

  1. #1

    [VB6] Winsock e HTTP

    Ciao a tutti, ho un problema con VB6 e Winsock che non riesco proprio a risolvere, sto scrivendo una DLL in VB6 che contiene una sola classe che espone una sola funzione.
    Tale funzione dovrebbe chiamare un indirizzo web, eseguire il parsing del testo ricevuto come risposta e restituire una parte del testo ricevuto.
    Ho incluso la libreria Winsock (MSWINSCK.OCX) come reference del progetto, all'interno della funzione istanzio un oggetto Winsock ed eseguo la connessione, la richiesta Http ed infine leggo la risposta.
    I test sono stati eseguiti attraverso un form che istanzia l'oggetto della DLL, chiama la funzione e mostra il risultato in una TextBox.

    Di seguito la funzione:

    codice:
    Public Function getSubstring(ByVal siteAddress As String) As String
        Dim winSck As Winsock
        Set winSck = New Winsock
    
        Dim tmpHttpRequest As String
        Dim tmpHttpResponse As String
    
        Dim tmpVariable As Integer
    
        tmpHttpRequest = "GET / HTTP/1.1" & vbNewLine & _
                        "Host: " & siteAddress & vbNewLine & _
                        "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" & vbNewLine & _
                        "Accept: text/plain, text/html" & vbNewLine & _
                        "Accept-Language: en" & vbNewLine & _
                        "Accept-Charset: utf-8" & vbNewLine & _
                        "Pragma: no-cache" & vbNewLine & _
                        "Connection: close" & vbNewLine & vbNewLine
        tmpHttpResponse = Empty
    
        winSck.RemoteHost = siteAddress
        winSck.RemotePort = 80
    
        If winSck.State <> sckClosed Then winSck.Close
        winSck.Connect
    
        Do While winSck.State <> sckConnected
            DoEvents
        Loop
        If winSck.State = sckConnected Then winSck.SendData tmpHttpRequest
    
        winSck.GetData tmpHttpResponse, vbString
        winSck.Close
    
        getSubstring = processResponse(tmpHttpResponse)
    
    End Function
    Il problema consiste nel fatto che la variabile tmpHttpResponse alla fine dell'esecuzione della funzione risulta essere vuota.

    Aggiungo un po' di informazioni raccolte nel corso del debugging:
    - se inserisco un breakpoint all'inizio della funzione e faccio procedere il programma "manualmente" (F8, F8, F8, etc) la variabile viene correttamente valorizzata, se lo eseguo senza breakpoint la stringa è vuota;
    - winSck.GetData e winSck.PeekData forniscono lo stesso risultato (stringa vuota);
    - ho inserito uno sleep prima dell'istruzione winSck.GetData (ho provato con tempi di attesa variabili da 0,5 fino a 8 secondi), il risultato non cambia (stringa vuota).

    Non riesco proprio a capire dov'è l'errore, ringrazio tutti anticipatamente per qualsiasi aiuto o suggerimento.
    Ciao
    Ma se sei uomo, ammira chi tenta grandi imprese, anche se fallisce.
    (Seneca, De vita beata, XX, 2)

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Il problema è semplice ... tra la SendData e la GetData deve passare il tempo necessario al sito per rispondere alla richiesta. Se la GetData viene eseguita prima della risposta, non avrai risultati.

    Il modo migliore è gestire la risposta tramite l'evento DataArrival del winsock, mettendolo opportunamente in attesa del completamento di tale evento.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Ciao oregon, innanzitutto grazie per l'intervento.
    Sto scrivendo una DLL e ho dovuto impostare i riferimenti a Winsock come se fosse una libreria activex (Menù: Project -> References), non posso fare quello che si fa di solito e aggiungerla come component (Menù: Project -> Components) e poi aggiungere il component in un un form. Il form non c'è proprio, ho solo una classe dentro la DLL e metodi funzioni della classe.
    Questo comporta che non ho a disposizione gli eventi di Winsock; solo proprietà e metodi (o funzioni).

    Ho pensato anch'io che si trattasse di un problema di attesa tra SendData e GetData e per fare debugging ho inserito una funzione sleep che tiene in standby l'esecuzione per un determinato tot di tempo.

    Il metodo Sleep era questo (dichiarato dentro un modulo bas):
    codice:
    Declare Sub Sleep Lib "kernel32" (ByVal milliseconds As Long)
    la successione SendData e GetData avveniva così
    codice:
        Do While winSck.State <> sckConnected
            DoEvents
        Loop
        If winSck.State = sckConnected Then winSck.SendData tmpHttpRequest
    
        Sleep 8000 ' dorme per 8 secondi
        winSck.GetData tmpHttpResponse, vbString
    Non ha funzionato. Sono andato anche oltre gli 8 secondi di attesa, il socket viene addirittura disconnesso dal server per timeout ma la tmpHttpResponse è sempre vuota.

    Credo ci sia qualcos'altro che sto sbagliando... ma non riesco proprio a capire.

    Grazie ancora per l'intervento.
    Ciao
    Ma se sei uomo, ammira chi tenta grandi imprese, anche se fallisce.
    (Seneca, De vita beata, XX, 2)

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Originariamente inviato da conger.conger
    Questo comporta che non ho a disposizione gli eventi di Winsock; solo proprietà e metodi (o funzioni).
    Questo non è vero ... gli eventi li hai ma devi indicarlo.

    In pratica, un codice funzionante potrebbe essere

    codice:
    Dim WithEvents winSck As Winsock
    Dim resAvail As Boolean
    Dim tmpHttpResponse As String
    
    Public Function getSubstring(ByVal siteAddress As String) As String
        Set winSck = New Winsock
    
        Dim tmpHttpRequest As String
        
        tmpHttpRequest = "GET / HTTP/1.1" & vbNewLine & _
                        "Host: " & siteAddress  & vbNewLine & _
                        "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" & vbNewLine & _
                        "Accept: text/plain, text/html" & vbNewLine & _
                        "Accept-Language: en" & vbNewLine & _
                        "Accept-Charset: utf-8" & vbNewLine & _
                        "Pragma: no-cache" & vbNewLine & _
                        "Connection: close" & vbNewLine & vbNewLine
        
        winSck.RemoteHost = siteAddress 
        winSck.RemotePort = 80
    
        resAvail = False
        
        If winSck.State <> sckClosed Then winSck.Close
        winSck.Connect
    
        Do While winSck.State <> sckConnected
            DoEvents
        Loop
        If winSck.State = sckConnected Then winSck.SendData tmpHttpRequest
        
        Do While Not resAvail
            DoEvents
        Loop
        winSck.Close
    
        Set winSck=Nothing
    
        ' Gestione tmpHttpResponse
        getSubstring = processResponse(tmpHttpResponse)
    End Function
    
    
    Private Sub winSck_DataArrival(ByVal bytesTotal As Long)
        winSck.GetData tmpHttpResponse, vbString
    
        resAvail = True
    End Sub
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Oregon, GRAZIE MILLE!!!
    Adesso funziona tutto perfettamente e non solo, ho imparato una cosa nuova: l'esistenza della keyword WithEvents, che mi consente di fare un sacco di cose che ignoravo di poter fare.

    Grazie ancora, per la soluzione del problema e per l'insegnamento!
    Ciao



    PS è necessario fare qualcosa per segnare il problema come risolto?
    Ma se sei uomo, ammira chi tenta grandi imprese, anche se fallisce.
    (Seneca, De vita beata, XX, 2)

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.