Página 1 de 1

[Plain C] Downloader solo con sockets, sin apis

Publicado: 23 Dic 2010, 22:25
por leos_79
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

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*/

}
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

Re: [Plain C] Downloader solo con sockets, sin apis

Publicado: 23 Dic 2010, 22:47
por BackSlash
Justamente ayer andaba leyendo sobre el protocolo HTTP para hacer algo así.

Haber que saco de esto

Re: [Plain C] Downloader solo con sockets, sin apis

Publicado: 23 Dic 2010, 22:56
por leos_79
[Enlace externo eliminado para invitados]

esa es la pagina del rfc de http, donde esta toda la documentacion del mismo.

otra cosa que te recomiendo es que pruebes con netcat o telnet , entrar a las webs.
o mismo crear servidores con nc y interactuar con los browsers.

saludos!

Re: [Plain C] Downloader solo con sockets, sin apis

Publicado: 24 Dic 2010, 00:01
por m4rtyr
muchas gracias lo estaba buscando
un syntax error en linea 44 olvidastes poner una semicolon ;
conectar(&cliente,"host.web.com",80);

bien explicado ;)

Re: [Plain C] Downloader solo con sockets, sin apis

Publicado: 24 Dic 2010, 03:49
por leos_79
uy debe ser cuando le agregue comentarios, el codigo esta muy verde se podrian mejorar varias cosas pero bueno, lo quise hacer rapido en medio dia jeje

muchas graciass m4rtyr tanto tiempo che!
espero que andes bien!

Re: [Plain C] Downloader solo con sockets, sin apis

Publicado: 24 Dic 2010, 11:19
por p0is0n-123
Está maravilloso bro...Sos todo un kapo ya programando en diferentes lenguajes.
Para Mejorar se podría hacer un control de datos para evitar fallos,como por ejemplo en la apertura de archivos y almacenamiento del puntero,todo se puede mejorar,pero aca no hay mucho que mejorar.

Gracias por invertir su valioso tiempo con nosotros....