Problema con cliente FTP en C

Iniciado por DrKillador, 27 Agosto 2013, 13:51 PM

0 Miembros y 1 Visitante están viendo este tema.

DrKillador

Hola amigos, estoy picandome un cliente ftp en C desde 0, para subir archivos a un FTP server. Llevo el siguiente código de momento, he conseguido autenticarme en el servidor ftp, pero al enviar el fichero archivo.txt, me lo crea vacío en el servidor, y no lo sube y me sale en el servidor como archivo vacio de 0bytes.

Alguien sabria decirme en que estoy fallando?

#pragma comment(lib, "wsock32.lib")
#include <stdio.h>
#include <windows.h>
#include <Winsock.h>

WSADATA ws;
char buf[10000];
void output(char *str)
{
     FILE *fp = fopen("output.txt", "a+");
     fprintf(fp, "%s\n", str);
     fclose(fp);
}

SOCKET ConnectFTP(char* ftpname, int port)
{
     WSAStartup(0x101, &ws);
     // Open up a socket for out TCP/IP session
     SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
     // Set up socket information.
     struct sockaddr_in a = {AF_INET, htons(port)};
     // Get the ip address of our ftp
     struct hostent *h = gethostbyname(ftpname);
     a.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)h->h_addr)));
     // Actually connect to the server
     connect(s, (struct sockaddr *)&a, sizeof(a));
     return s;
}

void receiving(SOCKET s, char* string)
{
     char aa[1000] = {'/0'};
     int ii = recv(s, aa, sizeof(aa), 0);
     sprintf(buf, "~%s~", aa);
     output(buf);
     if(string !=0)
           strcpy(string, aa);
}

void sending(SOCKET s, char* verb)
{
     strcpy(buf, verb);
     strcat(buf, "\r\n");
     output("Sending: ");
     output(buf);
     send(s, buf, strlen(buf), 0);
}

int _stdcall WinMain(HINSTANCE i, HINSTANCE j, char* k, int l)
{
     printf("Arrancando...\n");
     SOCKET s1 = ConnectFTP("ftp.XXXXXXXXXXXXX.com", 21);
     receiving(s1,0);
     printf("Enviando usuario...\n");
     sending(s1, "USER XXXXXX");
     receiving(s1,0);
     printf("Enviando contrasena...\n");
     sending(s1, "PASS XXXYYYZZZ");
     receiving(s1,0);
     sending(s1, "CWD web");
     sending(s1, "PASV");
     char szString[1000];
     receiving(s1, szString);
     printf("Sending ...\n");
     sending(s1, "STOR archivo.txt");
     sending(s1, "QUIT");
     receiving(s1,0);
     return 0;
}


El programa no me devuelve ningún error, a priori parece que funciona bien, aunque no sube el archivo, solo crea uno con el mismo nombre varcío

Gracias de antemano
Python <3 Python

eferion

Ante el envió de cualquier comando, el servidor FTP siempre responde con ACK o NACK. Deberías modificar el código para que sea sensible a los errores enviados por el servidor.

En cuanto a tu error... Estas enviando el mensaje "STOR archivo.txt"... Con eso estas diciéndole al servidor que le vas a enviar un archivo con nombre archivo.txt... Pero no le estas enviando el contenido.

Después de enviar ese comando tienes que abrir el archivo y enviarlo al servidor conforme a lo que dicte el estandard de FTP. Tu piensa que el servidor no tiene acceso al sistema de archivos del cliente... Por lo que no puede coger archivos así por las buenas.

DrKillador

Entiendo, muchas gracias.

Me he estado leyendo la RFC de FTP (http://www.rfc-es.org/rfc/rfc0959-es.txt) y sino he entendido mal, que sigo un poco liado he visto que para enviar el fichero, en mi caso TYPE A porque es de texto, habria que abrir simplemente un socket y enviar el contenido del archivo leido en modo texto. Por lo que he añadido el siguiente codigo despues del STOR:

char *ficheroA;
FILE *pFichero;
      char caracter;
      pFichero=fopen("a.txt", "rb");
      while (!feof(pFichero))
      {
          caracter = fgetc(pFichero);
          sprintf(ficheroA,"%s%c",ficheroA,caracter);
      }
      fclose(pFichero);

      sending(s1, ficheroA);


Y luego he leído que directamente con enviarle un QUIT ya da por cerrado el fichero. Pero sigue sin funcionarme y no me envia el archivo, solo me lo crea vacío.

¿Se me escapa algo?

Saludoss
Python <3 Python

eferion

FicheroA es un puntero a tipo char no inicializado. Si no quieres complicar te la vida, crea un buffer lo suficientemente grande como para almacenar los archivos de prueba. Si quieres hacerlo bien, calcula el tamaño del archivo y crea un buffer adecuado a su tamaño... luego no te olvides de liberar la memoria reservada.

Además la forma de leer el archivo es lo opuesto a optimización del rendimiento. Por cada carácter que lees del archivo realizas una copia de lo leído anteriormente y luego le añades el caracter leído. Además el buffer no esta inicializado luego lo que resulte de tu código es totalmente aleatorio.

Lo suyo es que leas el archivo del tirón o, si quieres hacerlo carácter a carácter, usa un int para almacenar el la posición en la que va el char y te olvidas de ese código diabólico que tienes.

Para asegurar que la lectura es correcta, saca el buffer por pantalla antes de enviar los datos al servidor.