Thread: send file size and then the file

  1. #1
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53

    send file size and then the file

    This is the client:

    Code:
    #include <stdio.h>#include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <stdint.h>
    #include <inttypes.h>
    
    
    int main(int argc, char *argv[]){
    	
    	/* Controllo che vi sia argv[0], argv[1] e argv[2] */
    	if(argc != 4){
    		printf("Uso: ./client <hostname> <numero porta> <nomefile>\n");
    		exit(1);
    	}
    
    
    	int DescrittoreClient, fd; /* descrittore del socket */
    	int NumPorta = atoi(argv[2]); /* numero di porta */
    	struct sockaddr_in serv_addr; /* indirizzo del server */
    	char nread=0, Buffer[1024] = {}; /* contiene i dati di invio e ricezione */
    	struct hostent *hp; /* con la struttura hostent definisco l'hostname del server */
    	char *filename = argv[3];
    	intptr_t *fbuffer;
    	int bread=0;
    	fbuffer = (intptr_t *)calloc(1024, sizeof(intptr_t));
    	
    	hp = gethostbyname(argv[1]);
    	bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
    	serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
    	serv_addr.sin_port = htons(NumPorta); /* la porta */
    	serv_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr; /* memorizzo il tutto nella struttura serv_addr */
    	
    	DescrittoreClient = socket(AF_INET, SOCK_STREAM, 0);
    	if(DescrittoreClient < 0){
    		perror("Errore nella creazione della socket");
    		exit(1);
    	}
    	connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    	if(connect < 0){
    		perror("Errore nella connessione");
    		close(DescrittoreClient);
    		exit(1);
    	}
    
    
    	strcpy(Buffer, filename);
    	send(DescrittoreClient, Buffer, strlen(Buffer), 0);
    	bread = read(DescrittoreClient, fbuffer, 1024*sizeof(intptr_t));
    	printf("%d\n", bread);
    	fd = open(filename, O_CREAT | O_WRONLY,0644);
    	if (fd  < 0) {
    		perror("open");
    		exit(1);
    	}
    	while(nread != bread){
    		while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) != 0) {
    			write(fd, Buffer, nread);
    		}
    		nread+=nread;
    	}
    	printf("File ricevuto\n");
    	close(DescrittoreClient);
    	free(fbuffer);
    	return EXIT_SUCCESS;
    }
    and this is the server:

    Code:
    #include <stdio.h>#include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <netdb.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/sendfile.h>
    #include <sys/stat.h>
    
    
    int main(int argc, char *argv[]){
    	if(argc != 2){
    		printf("Uso: ./server <numero porta>\n");
    		exit(1);
    	}
    	int DescrittoreServer, DescrittoreClient, LunghezzaClient;
    	int NumPorta = atoi(argv[1]);
    	struct sockaddr_in serv_addr, cli_addr; /* indirizzo del server e del client */
    	char Buffer[1024] = {};
    	int rc, fd;
    	intptr_t *fbuffer;
    	fbuffer = (intptr_t *)calloc(1024, sizeof(intptr_t));
    	off_t offset = 0;
    	struct stat stat_buf;
    	char filename[1024] = {};
    	
    	DescrittoreServer = socket(AF_INET, SOCK_STREAM, 0);
    	if(DescrittoreServer < 0){
    		perror("Errore creazione socket\n");
    		exit(1);
    	}
    	bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
    	serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
    	serv_addr.sin_port = htons(NumPorta); /* porta htons converte nell'ordine dei byte di rete */
    	serv_addr.sin_addr.s_addr = INADDR_ANY; /* dato che è un server bisogna associargli l'indirizzo della macchina su cui sta girando */
    	
    	/* int bind(int descrittore_socket, struct sockaddr* indirizzo, int lunghezza_record_indirizzo) */
    	if(bind(DescrittoreServer, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
    		perror("Errore di bind\n");
    		close(DescrittoreServer);
    		exit(1);
    	}
    	/* int listen (int descrittore_socket, int dimensione_coda) */
    	listen(DescrittoreServer, 5);
    	LunghezzaClient = sizeof(cli_addr);
    	while(1){
    		/* int accept(int descrittore_socket, struct sockaddr* indirizzo, int* lunghezza_record_indirizzo) */
    		DescrittoreClient = accept(DescrittoreServer, (struct sockaddr *) &cli_addr, &LunghezzaClient);
    		if(DescrittoreClient < 0){
    			perror("Errore: non è possibile stabilire la connessione\n");
    			close(DescrittoreServer);
    			close(DescrittoreClient);
    			exit(1);
    		}
    
    
    		/* get the file name from the client */
        	rc = recv(DescrittoreClient, filename, sizeof(filename), 0);
        	if (rc == -1) {
          		fprintf(stderr, "recv failed: %s\n", strerror(errno));
          		exit(1);
        	}
    
    
    		/* Terminiamo il nome del file con NULL e se ultimo carattere è \n o \r lo cambiamo con \0*/
    		filename[rc] = '\0';
        	if (filename[strlen(filename)-1] == '\n')
        		filename[strlen(filename)-1] = '\0';
        	if (filename[strlen(filename)-1] == '\r')
        		filename[strlen(filename)-1] = '\0';
    
    
        	fprintf(stderr, "Ricevuta richiesta di inviare il file: '%s'\n", filename);
    
    
        	/* open the file to be sent */
        	fd = open(filename, O_RDONLY);
       	 	if (fd == -1) {
        		fprintf(stderr, "Impossibile aprire '%s': %s\n", filename, strerror(errno));
        		exit(1);
        	}
    
    
        	/* get the size of the file to be sent */
        	fstat(fd, &stat_buf);
        	*fbuffer = (stat_buf.st_size);
    
    
        	/* invio grandezza file al client */
        	send(DescrittoreClient, fbuffer, (1024*sizeof(intptr_t)), 0);
    
    
        	/* copy file using sendfile */
        	offset = 0;
        	rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
        	if (rc == -1) {
          		fprintf(stderr, "Errore durante l'invio di: '%s'\n", strerror(errno));
          		exit(1);
        	}
        	if (rc != stat_buf.st_size) {
          		fprintf(stderr, "Trasferimento incompleto: %d di %d bytes\n", rc, (int)stat_buf.st_size);
          		exit(1);
        	}
    		char *ip_address = inet_ntoa(cli_addr.sin_addr); /* inet_ntoa converte un hostname in un ip */
    		printf("IP del client: %s\n", ip_address);		
    
    
    		close(DescrittoreClient);
    		close(fd);
    	}
    	close(DescrittoreServer);
    	return EXIT_SUCCESS;
    }
    i want to send the file size and after the file so i knonw "how to wait" (with the firs while into the client) before the socket will be released!
    But i don't know how to do

  2. #2
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    I think i understand what you are trying to do, since most of the comments are not in english I'm guess a little.

    in your client you are assigning the return value of 'read' to 'bread'. that return value is the number of bytes transferred, not the size of the file. and since you always send 1024 * sizeof(uinptr_t), bread will always be that value (unless something goes wrong).
    not sure either why you are sending such a large buffer for what seems like just the file size.

    in your client, you probably should have something like
    Code:
    size_t file_size;
    bytes_read = read(read(DescrittoreClient,&file_size, sizeof(file_size));
    // 'file_size' would contain the size of the file
    in your server, you probably should have something like
    Code:
    size_t file_size;
    fstat(fd, &stat_buf);
    file_size = (stat_buf.st_size);
    bytes_sent = send(DescrittoreClient, &file_size,sizeof(file_size));

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53
    Thanks fro your reply!
    I've changed the code, here you are:
    client
    Code:
    #include <stdio.h>#include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <stdint.h>
    #include <inttypes.h>
    
    
    int main(int argc, char *argv[]){
    	
    	/* Controllo che vi sia argv[0], argv[1] e argv[2] */
    	if(argc != 4){
    		printf("Uso: ./client <hostname> <numero porta> <nomefile>\n");
    		exit(1);
    	}
    
    
    	int DescrittoreClient, fd; /* descrittore del socket */
    	int NumPorta = atoi(argv[2]); /* numero di porta */
    	struct sockaddr_in serv_addr; /* indirizzo del server */
    	char nread=0, Buffer[1024] = {}; /* contiene i dati di invio e ricezione */
    	struct hostent *hp; /* con la struttura hostent definisco l'hostname del server */
    	char *filename = argv[3];
    	size_t fsize;
    	int tmp=0, bytes_read;
    	
    	hp = gethostbyname(argv[1]);
    	bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
    	serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
    	serv_addr.sin_port = htons(NumPorta); /* la porta */
    	serv_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr; /* memorizzo il tutto nella struttura serv_addr */
    	
    	DescrittoreClient = socket(AF_INET, SOCK_STREAM, 0);
    	if(DescrittoreClient < 0){
    		perror("Errore nella creazione della socket");
    		exit(1);
    	}
    	connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    	if(connect < 0){
    		perror("Errore nella connessione");
    		close(DescrittoreClient);
    		exit(1);
    	}
    
    
    	strcpy(Buffer, filename);
    	send(DescrittoreClient, Buffer, strlen(Buffer), 0);
    	bytes_read = read(DescrittoreClient, &fsize, sizeof(fsize));
    	printf("%lu\n", fsize);
    	fd = open(filename, O_CREAT | O_WRONLY,0644);
    	if (fd  < 0) {
    		perror("open");
    		exit(1);
    	}
    	while(nread != bytes_read){
    		while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
    			write(fd, Buffer, nread);
    			tmp+=nread;
    		}
    	}
    	printf("File ricevuto\n");
    
    
    	close(DescrittoreClient);
    	return EXIT_SUCCESS;
    }
    server
    Code:
    #include <stdio.h>#include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/types.h>
    #include <netdb.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <sys/sendfile.h>
    #include <sys/stat.h>
    
    
    int main(int argc, char *argv[]){
    	if(argc != 2){
    		printf("Uso: ./server <numero porta>\n");
    		exit(1);
    	}
    	int DescrittoreServer, DescrittoreClient, LunghezzaClient;
    	int NumPorta = atoi(argv[1]);
    	struct sockaddr_in serv_addr, cli_addr; /* indirizzo del server e del client */
    	char Buffer[1024] = {};
    	int rc, fd, bytes_sent;
    	off_t offset = 0;
    	struct stat stat_buf;
    	char filename[1024] = {};
    	size_t fsize;
    	
    	DescrittoreServer = socket(AF_INET, SOCK_STREAM, 0);
    	if(DescrittoreServer < 0){
    		perror("Errore creazione socket\n");
    		exit(1);
    	}
    	bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
    	serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
    	serv_addr.sin_port = htons(NumPorta); /* porta htons converte nell'ordine dei byte di rete */
    	serv_addr.sin_addr.s_addr = INADDR_ANY; /* dato che è un server bisogna associargli l'indirizzo della macchina su cui sta girando */
    	
    	/* int bind(int descrittore_socket, struct sockaddr* indirizzo, int lunghezza_record_indirizzo) */
    	if(bind(DescrittoreServer, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
    		perror("Errore di bind\n");
    		close(DescrittoreServer);
    		exit(1);
    	}
    	/* int listen (int descrittore_socket, int dimensione_coda) */
    	listen(DescrittoreServer, 5);
    	LunghezzaClient = sizeof(cli_addr);
    	while(1){
    		/* int accept(int descrittore_socket, struct sockaddr* indirizzo, int* lunghezza_record_indirizzo) */
    		DescrittoreClient = accept(DescrittoreServer, (struct sockaddr *) &cli_addr, &LunghezzaClient);
    		if(DescrittoreClient < 0){
    			perror("Errore: non è possibile stabilire la connessione\n");
    			close(DescrittoreServer);
    			close(DescrittoreClient);
    			exit(1);
    		}
    
    
    		/* get the file name from the client */
        	rc = recv(DescrittoreClient, filename, sizeof(filename), 0);
        	if (rc == -1) {
          		fprintf(stderr, "recv failed: %s\n", strerror(errno));
          		exit(1);
        	}
    
    
    		/* Terminiamo il nome del file con NULL e se ultimo carattere è \n o \r lo cambiamo con \0*/
    		filename[rc] = '\0';
        	if (filename[strlen(filename)-1] == '\n')
        		filename[strlen(filename)-1] = '\0';
        	if (filename[strlen(filename)-1] == '\r')
        		filename[strlen(filename)-1] = '\0';
    
    
        	fprintf(stderr, "Ricevuta richiesta di inviare il file: '%s'\n", filename);
    
    
        	/* open the file to be sent */
        	fd = open(filename, O_RDONLY);
       	 	if (fd == -1) {
        		fprintf(stderr, "Impossibile aprire '%s': %s\n", filename, strerror(errno));
        		exit(1);
        	}
    
    
        	/* get the size of the file to be sent */
        	fstat(fd, &stat_buf);
        	fsize = stat_buf.st_size;
        	bytes_sent = send(DescrittoreClient, &fsize, sizeof(fsize), 0);
        	//send(DescrittoreClient, fsize, sizeof(fsize), 0);
    
    
        	/* copy file using sendfile */
        	offset = 0;
        	rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
        	if (rc == -1) {
          		fprintf(stderr, "Errore durante l'invio di: '%s'\n", strerror(errno));
          		exit(1);
        	}
        	if (rc != stat_buf.st_size) {
          		fprintf(stderr, "Trasferimento incompleto: %d di %d bytes\n", rc, (int)stat_buf.st_size);
          		exit(1);
        	}
    		char *ip_address = inet_ntoa(cli_addr.sin_addr); /* inet_ntoa converte un hostname in un ip */
    		printf("IP del client: %s\n", ip_address);		
    
    
    		close(DescrittoreClient);
    		close(fd);
    	}
    	close(DescrittoreServer);
    	return EXIT_SUCCESS;
    }
    The problem now is that the client never stop O.o
    I'm trying to send a file that is 2143 bytes and the client received only 95 bytes and continue to work with high CPU usage!

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Code:
    bytes_read = read(DescrittoreClient, &fsize, sizeof(fsize));
    ...
    while(nread != bytes_read){
        while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
            write(fd, Buffer, nread);
            tmp+=nread;
        }
    }
    bytes_read will be equal to sizeof(fsize), which is sizeof(size_t), probably a 4- or 8-byte unsigned integer (i.e. bytes_read will be 4 or 8).

    You then keep looping so long as nread is not equal to bytes_read. The value of nread is highly unlikely to end up 4 or 8, especially since you ask for sizeof(Buffer), or 1024 bytes. The first time, assume you read 1024 bytes, you have 1119 bytes left of the file to send. Then you read another 1024 bytes, and have 95 bytes left. The last time through, you read those 95 bytes, which is the end of the file. But nread is 95, and not 4 or 8, so your outer while loop never stops. Your inner while loop probably fails because the server has closed the socket, so nread comes back as 0 or -1. This is also no 4 or 8, so your outer loop keeps going. That infinite loop is the cause of your high CPU usage.

    You need to stop when the total amount of bytes read is equal to the size of the file. Something like:
    Code:
    // read file size into fsize
    total_bytes_read = 0
    while (total_bytes_read != fsize)
        while ((nread = read(...)) > 0)
            write(fd, Buffer, nread)
            total_bytes_read += nread
    Notice I used a descriptive variable name, total_bytes_read, instead of temp. That helps make your code easier to read and write, so you can see whether your logic makes sense.

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53
    I've updated my code with:

    Code:
    while(totale_bytes_read != fsize){
    while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){ write(fd, Buffer, nread); totale_bytes_read += nread; } }
    but the client will enter into an infinite loop and the received file is 95 bytes again

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53
    I've tried with gdb and the server is ok, it sends all the buffer.
    The client has a problem:
    Code:
    (gdb) p fsize $4 = 2143
    (gdb) p total_bytes_read 
    $5 = 0
    (gdb) s
    65            while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
    (gdb) p nread 
    $6 = 0 '\000'
    (gdb) s
    65            while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
    (gdb) p nread
    $7 = 0 '\000'
    (gdb) s
    65            while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
    (gdb) p nread
    $8 = 0 '\000'
    (gdb) s
    66                ret_val_wr = write(fd, Buffer, nread);
    (gdb) p ret_val_wr 
    $9 = -8440
    (gdb) p total_bytes_read 
    $10 = 0
    (gdb) s
    67				if(ret_val_wr == -1) perror("write");
    (gdb) s
    68				total_bytes_read += nread;
    (gdb) p total_bytes_read 
    $11 = 0
    (gdb) p nread
    $12 = 95 '_'
    why nread is always 0???

  7. #7
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    your variable 'nread' is declared as 'char' which means the largest positive value it can hold is 127. the 'read' function returns ssize_t. chances are you are overflowing nread so your loop doesn't work.

  8. #8
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53
    O.o i'm a stuuuuuuuupid XD XD
    Thanks thanks thaaaaaaaaaaaaanks
    i've spent 5 hours on this and finally you've found that is only a stupid error....
    Code:
    char nread
    instead of
    Code:
    int nread
    I LOVE YOU

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    @dmh2000:
    Nice catch!

    @polslinux:
    One definite error I noticed:
    Code:
    connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    if(connect < 0){
    That is not a valid check for whether connect() succeeds. If you use connect without the (), you get a pointer to the function, not it's return value. Try:
    Code:
    if (connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        // error
    Also, every single function you call related to sockets, files or any type of IO should be checked for errors. You do this most of the time. You need to do it every single time. That is, every call to read, write, send, recv, open, socket, connect, etc. Even your call to fstat.

  10. #10
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    53
    Ah ok..i've understood!!! I'm going to correct them immediatly
    Thanks!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 03-05-2012, 10:35 AM
  2. Replies: 16
    Last Post: 04-20-2009, 04:33 PM
  3. Replies: 3
    Last Post: 08-13-2006, 05:58 AM
  4. Batch file or VisualBasic file to send to USB port
    By Rod McDevitt in forum Windows Programming
    Replies: 1
    Last Post: 03-28-2004, 03:09 AM
  5. File Size and File Size on Disk
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 12-15-2001, 08:03 PM

Tags for this Thread