[SOLUCIONADO] Ayuda con código para transferencia de archivos en C

Iniciado por proxy_lainux, Agosto 01, 2016, 11:45:42 PM

Tema anterior - Siguiente tema

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

Agosto 01, 2016, 11:45:42 PM Ultima modificación: Agosto 02, 2016, 04:42:31 PM por Gabriela
Hola

No sé si mi pregunta va en esta zona, pero bueno, espero no poner desorden.

Estaba intentando hacer un programa que me realice una transferencia de archivos basado en C en linux, después de analizar el código, no logro hacerlo funcionar, ya que lo único que logro mandar es un archivo txt e incompleto, y los demás archivos no los logro mandar correctamente.

Espero haya alguien aquí que me pueda ayudar revisando lo que hice y espero me pueda ayudar diciendome que estoy haciendo mal. Hace unos años lo intenté y logré hacerlo funcionar, pero perdí el código y ahora no recuerdo que hice, pero la idea de como lo inicié aún la recuerdo, sin embargo, no logro entender que estoy haciendo mal esta vez.

Dejaré el código, solo espero sea entendible ya que moví varias cosas para hacerlo funcionar.

Servidor

Código: c
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>


int main(){

int sockfd, bytenumero;
struct sockaddr_in re;
int sin_size, confd;
long bff, bfin, erecv;
char buf[1024];

sockfd = socket(AF_INET, SOCK_STREAM, 0);

re.sin_family = AF_INET;
re.sin_port = htons(33371);
re.sin_addr.s_addr = INADDR_ANY;
memset(re.sin_zero, 0, 8);

bind(sockfd, (struct sockaddr*)&re, sizeof(struct sockaddr));

sin_size = sizeof(struct sockaddr_in);

listen(sockfd, 10);

sockfd = accept(sockfd, (struct sockaddr *)&re, &sin_size);

recv(sockfd, (char*)bff, sizeof(long), 0);
bfin = ntohl(*((long*)bff));

send(sockfd, "listo", 5, 0);

printf("%d", bfin);

FILE *flito = fopen("/home/grimoire/ko.txt", "wb");

erecv = 0;
bytenumero = 0;

while(erecv < bfin){
   
    bytenumero = recv(sockfd, buf, sizeof(buf), 0);
    fwrite(buf, 1, bytenumero, flito);
   
    erecv = erecv + bytenumero;
    printf("%d", erecv);
   
}


fclose(flito);
close(sockfd);

return 0;

}


Cliente

Código: c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>


int main(){


int leido;
int sockfd, ienv;
long siz, zout;
struct hostent *he;
struct sockaddr_in t_add;
FILE *pfile, *flista;
char bff[5];
char bufer[1024];

he = gethostbyname("127.0.0.1");

sockfd = socket(AF_INET, SOCK_STREAM, 0);

t_add.sin_family = AF_INET;
t_add.sin_port = htons(33371);
t_add.sin_addr = *((struct in_addr*)he->h_addr);
memset(t_add.sin_zero,0, 8);


  connect(sockfd, (struct sockaddr*)&t_add, sizeof(struct sockaddr));
 
  pfile = fopen("/home/grimoire/korn.txt", "rb");
  fseek(pfile, 0, SEEK_END);
  siz = ftell(pfile);
  rewind(pfile);
 
  zout = htonl(siz);
 
  printf("%ld", siz);

  send(sockfd, (char*)&zout, sizeof(zout), 0);
 
  recv(sockfd, bff, sizeof(bff), 0);
 
  printf("\n%s\n", bff);
 
  ienv = 0;
  leido = 0;
 
  if(flista != NULL)
 
  while(!feof(pfile)){
   
    leido = fread(bufer, 1, sizeof(bufer), pfile);
    send(sockfd, bufer, leido, 0);
    ienv = ienv + leido;
   
    printf("%d", ienv);
   
  }
 
 
  fclose(pfile);
  close(sockfd);
 
  return 0;

}




Agosto 02, 2016, 04:20:41 AM #1 Ultima modificación: Agosto 02, 2016, 04:44:12 AM por grep
Hola,

voy a remarcar secciones puntuales sólo para que el código funcione.

Comenzando con el cliente,

veo que tienes la siguiente línea:

Código: c
zout = htonl(siz);


No veo necesario ningún byte ordering más que el de tu máquina. Esto me lleva a borrar esta línea y cambiar el código de send:

Código: c

// send(sockfd, (char*)&zout, sizeof(zout), 0);
send(sockfd, &siz, sizeof siz, 0);


Finalmente veo que tienes esta línea que no le veo utilidad alguna:

Código: c

if(flista != NULL) // debes comentar o borrar esta línea



Ahora con el server,

debes corregir tu primer llamada a recv():

Código: c

// recv(sockfd, (char*)bff, sizeof(long), 0);
recv(sockfd, &bff, sizeof(long), 0);


Además no veo necesario realizar el byte ordering, el cual se encuentra en la asignación a la variable bfin:

Código: c
bfin = ntohl(*((long*)bff)); // debes comentar o borrar esta línea


En consecuencia debes cambiar las líneas en donde utilizas bfin:

Código: c

// printf("%d", bfin);
printf("%d", bff);

.
.
.

// while(erecv < bfin){
while(erecv < bff) {



Saludos

Gracias, ah funcionado.

No tenía idea de que htonl se usara para ordenar bytes en el network, yo creía que era para pasar variables long, en este caso pasar el long de la variable donde guarde el tamaño del archivo. pero efectivamente lo quite como mencionas e igual recibí el tamaño del archivo.

Pero ya funciona, gracias por la ayuda :)