La Web del Programador: Comunidad de Programadores
 
    Pregunta:  55115 - DESCARGAR HTTP CON WINSOCK
Autor:  Ignacio Martín Cordón
Tengo una rutina que conecta a una dirección web mediante winsock y solicita un fichero usando el comando:
oSOCK.SendData("GET "+cOrigen+" HTTP/1.1"+CHR(13)+CHR(10)+"Host: "+cHost+CHR(13)+CHR(10)+"Accept: */*"+CHR(13)+CHR(10)+"Connection: close"+CHR(13)+CHR(10)+CHR(13)+CHR(10))

Mi problema es que cuando el documento que se trae es pequeño (pocos megas) funciona correctamente casi el 100% de las veces. Pero con documentos de mayor tamaño pasan cosas raras como por ejemplo:
· Sólo un 3% de las veces llega a descargar el 100% del documento. Casi siempre se desconecta el socket cuando falta un paquete por llegar.
· La información que se recibe no es correcta. He comparado los paquetes que recibo con los que debería recibir y uno de cada 50 contiene errores.

¿Qué puede estar ocurriendo?
Suprimir la cláusula "Connection: close" no tiene ningún efecto adverso ni positivo.
Tampoco se aprecian mejoras sin en lugar de usar el método DataArrival empleo un timer llamando a GetData yo mismo.

Gracias.

  Respuesta:  Claudio Romero
En esta pagina
http://www.fpress.com/revista/Num9709/Sep97.htm

Hay una rutina en Foxpro para bajar un archivo a disco de texto o binario
por ej:

DO VFPHTTP WITH "http://www.linux.org","c:linux.htm"
o
DO VFPHTTP WITH "http://mirror.pacific.net.au/linux/slackware/slackware-12.2/slackware/l/aspell-0.60.5-i486-2.tgz","c:aspell.tgz"

Utiliza la api de wininet.dll, que funciona bien para archivos de cualquier tamaño,
aunque yo la utilice desde delphi, son las mismas funciones.

**Esta es la rutina
PROCEDURE VFPHTTP
LPARAMETER cURL, cNameFich
*** Definición de constantes básicas
#DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0
*** Declaración de funciones del API
DECLARE LONG GetLastError ;
IN WIN32API
DECLARE INTEGER InternetCloseHandle ;
IN "wininet.dll" ;
LONG hInet
DECLARE LONG InternetOpen ;
IN "wininet.dll" ;
STRING lpszAgent, ;
LONG dwAccessType, ;
STRING lpszProxyName, ;
STRING lpszProxyBypass, ;
LONG dwFlags
DECLARE LONG InternetOpenUrl ;
IN "wininet.dll" ;
LONG hInet, ;
STRING lpszUrl, ;
STRING lpszHeaders, ;
LONG dwHeadersLength, ;
LONG dwFlags, ;
LONG dwContext
DECLARE LONG InternetReadFile ;
IN "wininet.dll" ;
LONG hFtpSession, ;
STRING @lpBuffer, ;
LONG dwNumberOfBytesToRead, ;
LONG @lpNumberOfBytesRead
*** Apertura
nInternet = InternetOpen( ;
"pruebavfp", ;
INTERNET_OPEN_TYPE_PRECONFIG, ;
"", "", 0 )
IF nInternet = 0
MESSAGEBOX( "Error: " ;
+ LTRIM( STR( GetLastError() ) ) ;
+ " en InternetOpen.", 16 )
RETURN
ENDIF
*** Abrir el URL
nFichHTTP = InternetOpenUrl ( ;
nInternet, ;
cUrl, ;
NULL, 0, 0, 0 )
IF nFichHTTP = 0
MESSAGEBOX( "Error: " ;
+ LTRIM( STR( GetLastError() ) ) ;
+ " en InternetOpenUrl.", 16 )
InternetCloseHandle( nInternet )
RETURN
ENDIF
*** Abir el fichero en el cliente
nFich = FCREATE( cNameFich )
*** Contruir las variables necesarias
nTama = 0
nLen = 1
*** Bucle de lectura
DO WHILE nLen # 0
cBuffer = REPLICATE( CHR(0), 2048 )
*** Leer del fichero en el servidor
InternetReadFile( ;
nFichHTTP, ;
@cBuffer, ;
LEN( cBuffer ), ;
@nLen )
*** Escribir el fichero en el cliente
FWRITE( ;
nFich, ;
SUBSTR( cBuffer, 1, nLen ) )
*** Aumentar el tamaño total
nTama = nTama + nLen
WAIT WIND "Recibidos " ;
+ LTRIM( STR( nTama ) ) NOWAIT
ENDDO
WAIT CLEAR
*** Cerrar el fichero local
FCLOSE( nFich )
*** Cierre del uso del API
InternetCloseHandle( nInternet )