Ver Mensaje Individual
  #11 (permalink)  
Antiguo 30/08/2013, 05:18
Avatar de jja
jja
 
Fecha de Ingreso: diciembre-2010
Ubicación: BCN
Mensajes: 47
Antigüedad: 13 años, 10 meses
Puntos: 0
Respuesta: Problema con cliente FTP en C

Al final lo tengo casi resuelto aunque me queda un problema. Si el fichero es pequeño y lo envío en un solo paquete todo va bien, pero si lo envío a trozos porque es más grande que el tamaño del buffer, no me llega el archivo entero al servidor, y además llega con símbolos raros . Los estoy leyendo correctamente, pero se pierden paquetes en el envío por lo que no debo estar enviando la información correctamente por el socket.

De hecho, he comprobado que solo llega "bien" el primer paquete, los siguientes llegan con símbolos raros:

Código C:
Ver original
  1. #pragma comment(lib, "wsock32.lib")
  2. #include <stdio.h>
  3. #include <windows.h>
  4. #include <Winsock.h>
  5.  
  6. WSADATA ws;
  7. char buf[10000];
  8.  
  9. void output(char *str)
  10. {
  11.       FILE *fp = fopen("output.txt", "a+");
  12.       fprintf(fp, "%s\n", str);
  13.       fclose(fp);
  14. }
  15.  
  16. SOCKET Connect(char* ftpname, int port)
  17. {
  18.       WSAStartup(0x101, &ws);
  19.       // Open up a socket for out TCP/IP session
  20.       SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
  21.       // Set up socket information.
  22.       struct sockaddr_in a = {AF_INET, htons(port)};
  23.       // Get the ip address of our ftp
  24.       struct hostent *h = gethostbyname(ftpname);
  25.       a.sin_addr.s_addr = inet_addr(inet_ntoa(*((struct in_addr *)h->h_addr)));
  26.       // Actually connect to the server
  27.       connect(s, (struct sockaddr *)&a, sizeof(a));
  28.       return s;
  29. }
  30.  
  31. void receiving(SOCKET s, char* string)
  32. {
  33.       char aa[1000] = {'/0'};
  34.       int ii = recv(s, aa, sizeof(aa), 0);
  35.       sprintf(buf, "~%s~", aa);
  36.       output(buf);
  37.       if(string !=0)
  38.             strcpy(string, aa);
  39. }
  40.  
  41. void sending(SOCKET s, char* verb)
  42. {
  43.       strcpy(buf, verb);
  44.       strcat(buf, "\r\n");
  45.       output("Sending: ");
  46.       output(buf);
  47.       send(s, buf, strlen(buf), 0);
  48. }
  49.  
  50. int _stdcall WinMain(HINSTANCE i, HINSTANCE j, char* k, int l)
  51. {
  52.       //Creacion de socket para conectar con FTP
  53.       SOCKET s1 = Connect("ftp.xxxxxxxxxxxxxxx.com", 21);
  54.       receiving(s1,0);
  55.  
  56.       //Envio de usuario
  57.       sending(s1, "USER xxxxxxx");
  58.       receiving(s1,0);
  59.  
  60.       //Envio de contraseña
  61.       sending(s1, "PASS yyyyyyyyyy");
  62.       receiving(s1,0);
  63.  
  64.       //Envio de tipo de archivos que aceptará, en este caso binarios
  65.       sending(s1, "TYPE I");
  66.       receiving(s1, 0);
  67.  
  68.       char strPasv[1000];
  69.  
  70.       //Enviamos la activación del modo pasivo
  71.       sending(s1, "PASV");
  72.       receiving(s1, strPasv);
  73.       printf("%s\n",strPasv);
  74.  
  75.       //Parseamos para quedarnos exclusivamente con la IP y el puerto
  76.       int cont=0;
  77.       int hostFound=0;
  78.       int salida=0;
  79.       char ipHost[24]="";
  80.       while((cont<sizeof(strPasv))&&(!salida))
  81.       {
  82.            if(strPasv[cont]=='(')
  83.            {
  84.                hostFound=1;
  85.            }
  86.            else if(strPasv[cont]==')')
  87.            {
  88.                salida=1;
  89.            }
  90.            else if(hostFound)
  91.            {
  92.                sprintf(ipHost,"%s%c",ipHost,strPasv[cont]);
  93.            }
  94.            cont++;
  95.       }
  96.  
  97.       char *trozos;
  98.  
  99.       //Separamos los trozos por las comas
  100.       trozos = strtok(ipHost,",");
  101.  
  102.       //Por cada trozo leido, la introduciremos en su correspondiente variable
  103.       char ipFTP2[16]="";
  104.       int hp=0;
  105.       int lp=0;
  106.       for(i=0;trozos;i++)
  107.       {
  108.             //Almacenamos cada trozo en la IP
  109.             if(i<16)
  110.             {
  111.                 if(i==0)
  112.                 {
  113.                     sprintf(ipFTP2,"%s%s",ipFTP2,trozos);
  114.                 }
  115.                 else
  116.                 {
  117.                     sprintf(ipFTP2,"%s.%s",ipFTP2,trozos);
  118.                 }
  119.             }
  120.             //Almacenamos el último trozo en el puerto
  121.             else if(i>=16)
  122.             {
  123.                 if(i==16)
  124.                 {
  125.                     hp=atoi(trozos);
  126.                 }
  127.                 else
  128.                 {
  129.                     lp=atoi(trozos);
  130.                 }
  131.  
  132.             }
  133.             trozos=strtok(0,",");
  134.       }
  135.       int portFTP2 = (hp*256) + lp;
  136.       printf("IP: %s - PASSIVE PORT: %d\n", ipFTP2, portFTP2);
  137.       //Fin del parseador
  138.  
  139.       //Enviamos STOR para crear el fichero en el FTP y comenzar el envio por el socket s2
  140.       char strS1[1000];
  141.       sending(s1, "STOR c.txt");
  142.  
  143.       //Creamos segundo socket para conectar a la IP y PUERTO brindados por el server para el envio
  144.       SOCKET s2 = Connect(ipFTP2, portFTP2);
  145.  
  146.       //Lectura de archivo en modo binario
  147.       char buf1[512]="";
  148.       int total=0;
  149.       FILE *pFichero;
  150.       pFichero=fopen("c.txt", "rb");
  151.       while (!feof(pFichero))
  152.       {
  153.           int bytesR = fread (buf1, sizeof(char), sizeof(buf1), pFichero);
  154.           if( ferror( pFichero ) )      {
  155.              printf( "Read error\n" );
  156.              break;
  157.           }
  158.           total+=bytesR;
  159.           send(s2, buf1, strlen(buf1), 0);
  160.       }
  161.       fclose(pFichero);
  162.       printf("Total de bytes enviados: %d\n",total);
  163.  
  164.       //Cierro socket 2
  165.       sending(s2, "QUIT");
  166.  
  167.       //Cierro socket 1
  168.       sending(s1, "QUIT");
  169.       receiving(s1,0);
  170.       return 0;
  171. }

Hay que enviar algún tipo de flag o similar en los paquetes, o codificar en b64 durante el envío del contenido del archivo leído?

Graciass
__________________
El supremo arte de la guerra es someter al enemigo sin luchar.

Sun Tzu

Última edición por jja; 30/08/2013 a las 10:27