[Plain C] Downloader solo con sockets, sin apis
Publicado: 23 Dic 2010, 22:25
Bueno les traigo aqui un downloader de bajo nivel, el cual hace uso del protocolo Http
para bajar un archivo alojado en un servidor web, emulando al google chrome.
Lo que hace es enviar una peticion GET /archivo.zip seguido de las cabeceras del google chrome.
El servidor envia una respuesta, y el codigo esta basado en un parseo "berreta" pero funciona.
para publicarlo rapido, no hice mucho chequeo de errores, pero bueno supongo que el que este entusiasmado en esto
los podra realizar, ademas esta hardcodeado.
el que quiera probarlo con una web suya,
tiene que cambiar lo siguiente que esta en negrita
char sbuf[] = "GET //archivo.zip HTTP//1.1 \nHost: host.web.com:80
conectar(&cliente,"host.web.com",80)
f =fopen("C:\\archivolocal.zip","wb");
el codigo tambien incluye una funcion conectar que seguramente a muchos les sirva
para no lidear con los sockets en c, la misma fue hecha por mi para una materia de la facultad jeje
Testeado en VC 2005 express
en fin espero que les sirva para comprender como funcionan esas apis de windows, que no es nada mas que
comunicacion entre sockets saludos.
Leos =D
para bajar un archivo alojado en un servidor web, emulando al google chrome.
Lo que hace es enviar una peticion GET /archivo.zip seguido de las cabeceras del google chrome.
El servidor envia una respuesta, y el codigo esta basado en un parseo "berreta" pero funciona.
para publicarlo rapido, no hice mucho chequeo de errores, pero bueno supongo que el que este entusiasmado en esto
los podra realizar, ademas esta hardcodeado.
el que quiera probarlo con una web suya,
tiene que cambiar lo siguiente que esta en negrita
char sbuf[] = "GET //archivo.zip HTTP//1.1 \nHost: host.web.com:80
conectar(&cliente,"host.web.com",80)
f =fopen("C:\\archivolocal.zip","wb");
el codigo tambien incluye una funcion conectar que seguramente a muchos les sirva
para no lidear con los sockets en c, la misma fue hecha por mi para una materia de la facultad jeje
Código: Seleccionar todo
#include <stdio.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
/*funcion conectar creada por mi*/
/*se le envia un socket , un host y un puerto y conecta*/
int conectar(int* soquete,char *remoteHost,int remotePort)
{
WSADATA wsaData;
struct hostent *he; //estructura necesaria para transformar de "host.server.com" a direccion ip
struct sockaddr_in dest_addr;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0) //inicializo WSAStartup
{
exit(1);
}
he=gethostbyname(remoteHost);
dest_addr.sin_family = AF_INET; // Ordenación de máquina
dest_addr.sin_port = htons(remotePort); // short, Ordenación de la red
dest_addr.sin_addr.s_addr = inet_addr(remoteHost);
dest_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(dest_addr.sin_zero), '\0', 8); // Poner a cero el resto de la estructura
*soquete = socket(AF_INET, SOCK_STREAM, 0);
return connect(*soquete, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)); /* en el segundo parametro, lo que esta entre parentesis es una declaracion, de un puntero a cual le asigno , a donde apunta dest_addr*/
}
int main()
{
int cliente=0,i=0;
char sbuf[] = "GET //archivo.zip HTTP//1.1 \nHost: host.web.com:80 \nConnection: keep-alive \nCache-Control: max-age=0 \nAccept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 \nUser-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.224 Safari/534.10 \nAccept-Encoding: gzip,deflate,sdch \nAccept-Language: es-419,es;q=0.8 \nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 \n\n";
char rbuf[1024];char rbuf2[1024];
char *p;
FILE *f;
int byrectot=0,byrec=0,tamaniof=0;
while (cliente == 0) /*loop para conectar*/
{
conectar(&cliente,"host.web.com",80)
}
send(cliente, sbuf,strlen(sbuf),0); /*envio al servidor la peticion del get */
f =fopen("C:\\archivo.zip","wb"); /*archivo local a guardar*/
byrectot = recv(cliente,rbuf,sizeof(rbuf),0); /*recibo la cabecera junto con algunos bytes*/
memcpy (rbuf2,rbuf,sizeof(rbuf)+1); //hago una copia a una auxiliar, para tratar la cabecera
/*para sacar tamanio*/
p = strtok(rbuf,": ");
while (strstr(p,"Len") == 0) /*recorro la cabecera hasta encontrar "len"*/
{
p = strtok(NULL,": ");
}
p = strtok(NULL,": "); /*recorto entre : */
p = strtok(p,"\r\n"); /*recorto entre fin de linea y entonces me quedan los bytes a recibir*/
tamaniof = atoi(p); /*los meto en una variable*/
/*sacar cabecera. la cabecera termina en \r\n\r\n */
while ( !((rbuf2[i+1] == '\r') && (rbuf2[i+2] == '\n') && (rbuf2[i+3] == '\r') && (rbuf2[i+4] == '\n')) )
{
i++;
}
i = i+5; /*salteo los caracteres de fin*/
byrectot= byrectot-i; /*tamaño recibido real de archivo (restando cabecera)*/
fwrite(&rbuf2[i],1,byrectot,f); /*escribir a archivo*/
while (tamaniof > byrectot) /*hay mas?*/
{
byrec = recv(cliente,rbuf,sizeof(rbuf),0); //recibo los siguientes bytes y guardo la cantidad
byrectot = byrectot + byrec; /*contador de total recibidos */
fwrite(rbuf,1,byrec,f); /*escribo al archivo los bytes recibidos*/
}
fclose(f); /*se termino cierro*/
}
en fin espero que les sirva para comprender como funcionan esas apis de windows, que no es nada mas que
comunicacion entre sockets saludos.
Leos =D