Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - socket C inviare e riceve un file
Forum - C/C++ - socket C inviare e riceve un file

Avatar
polslinux (Normal User)
Newbie


Messaggi: 2
Iscritto: 25/06/2012

Segnala al moderatore
Postato alle 19:17
Lunedì, 25/06/2012
Codice del client:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <sys/types.h>
  9. #include <netdb.h>
  10. #include <fcntl.h>
  11. #include <stdint.h>
  12. #include <inttypes.h>
  13.  
  14. int main(int argc, char *argv[]){
  15.        
  16.         /* Controllo che vi sia argv[0], argv[1] e argv[2] */
  17.         if(argc != 4){
  18.                 printf("Uso: ./client <hostname> <numero porta> <nomefile>\n");
  19.                 exit(1);
  20.         }
  21.  
  22.         int DescrittoreClient, fd; /* descrittore del socket */
  23.         int NumPorta = atoi(argv[2]); /* numero di porta */
  24.         struct sockaddr_in serv_addr; /* indirizzo del server */
  25.         char nread=0, Buffer[1024] = {}; /* contiene i dati di invio e ricezione */
  26.         struct hostent *hp; /* con la struttura hostent definisco l'hostname del server */
  27.         char *filename = argv[3];
  28.         size_t fsize;
  29.         int tmp=0, bytes_read;
  30.        
  31.         hp = gethostbyname(argv[1]);
  32.         bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
  33.         serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
  34.         serv_addr.sin_port = htons(NumPorta); /* la porta */
  35.         serv_addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr)) -> s_addr; /* memorizzo il tutto nella struttura serv_addr */
  36.        
  37.         DescrittoreClient = socket(AF_INET, SOCK_STREAM, 0);
  38.         if(DescrittoreClient < 0){
  39.                 perror("Errore nella creazione della socket");
  40.                 exit(1);
  41.         }
  42.         connect(DescrittoreClient, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
  43.         if(connect < 0){
  44.                 perror("Errore nella connessione");
  45.                 close(DescrittoreClient);
  46.                 exit(1);
  47.         }
  48.  
  49.         strcpy(Buffer, filename);
  50.         send(DescrittoreClient, Buffer, strlen(Buffer), 0);
  51.         bytes_read = read(DescrittoreClient, &fsize, sizeof(fsize));
  52.         if(bytes_read == -1){
  53.                 printf("Errore durante ricezione grandezza file\n");
  54.                 close(DescrittoreClient);
  55.                 exit(1);
  56.         }
  57.  
  58.         fd = open(filename, O_CREAT | O_WRONLY,0644);
  59.         if (fd  < 0) {
  60.                 perror("open");
  61.                 exit(1);
  62.         }
  63.        
  64.         while(nread != bytes_read){
  65.                 while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
  66.                         write(fd, Buffer, nread);
  67.                         tmp+=nread;
  68.                 }
  69.         }
  70.         printf("File ricevuto\n");
  71.  
  72.         close(DescrittoreClient);
  73.         return EXIT_SUCCESS;
  74. }



e codice del server:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <sys/types.h>
  9. #include <netdb.h>
  10. #include <errno.h>
  11. #include <fcntl.h>
  12. #include <sys/sendfile.h>
  13. #include <sys/stat.h>
  14.  
  15. int main(int argc, char *argv[]){
  16.         if(argc != 2){
  17.                 printf("Uso: ./server <numero porta>\n");
  18.                 exit(1);
  19.         }
  20.         int DescrittoreServer, DescrittoreClient, LunghezzaClient;
  21.         int NumPorta = atoi(argv[1]);
  22.         struct sockaddr_in serv_addr, cli_addr; /* indirizzo del server e del client */
  23.         char Buffer[1024] = {};
  24.         int rc, fd, bytes_sent;
  25.         off_t offset = 0;
  26.         struct stat stat_buf;
  27.         char filename[1024] = {};
  28.         size_t fsize;
  29.        
  30.         DescrittoreServer = socket(AF_INET, SOCK_STREAM, 0);
  31.         if(DescrittoreServer < 0){
  32.                 perror("Errore creazione socket\n");
  33.                 exit(1);
  34.         }
  35.         bzero((char *) &serv_addr, sizeof(serv_addr)); /* bzero scrive dei null bytes dove specificato per la lunghezza specificata */
  36.         serv_addr.sin_family = AF_INET; /* la famiglia dei protocolli */
  37.         serv_addr.sin_port = htons(NumPorta); /* porta htons converte nell'ordine dei byte di rete */
  38.         serv_addr.sin_addr.s_addr = INADDR_ANY; /* dato che è un server bisogna associargli l'indirizzo della macchina su cui sta girando */
  39.        
  40.         /* int bind(int descrittore_socket, struct sockaddr* indirizzo, int lunghezza_record_indirizzo) */
  41.         if(bind(DescrittoreServer, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
  42.                 perror("Errore di bind\n");
  43.                 close(DescrittoreServer);
  44.                 exit(1);
  45.         }
  46.         /* int listen (int descrittore_socket, int dimensione_coda) */
  47.         listen(DescrittoreServer, 5);
  48.         LunghezzaClient = sizeof(cli_addr);
  49.         while(1){
  50.                 /* int accept(int descrittore_socket, struct sockaddr* indirizzo, int* lunghezza_record_indirizzo) */
  51.                 DescrittoreClient = accept(DescrittoreServer, (struct sockaddr *) &cli_addr, &LunghezzaClient);
  52.                 if(DescrittoreClient < 0){
  53.                         perror("Errore: non è possibile stabilire la connessione\n");
  54.                         close(DescrittoreServer);
  55.                         close(DescrittoreClient);
  56.                         exit(1);
  57.                 }
  58.  
  59.                 /* get the file name from the client */
  60.         rc = recv(DescrittoreClient, filename, sizeof(filename), 0);
  61.         if (rc == -1) {
  62.                 fprintf(stderr, "recv failed: %s\n", strerror(errno));
  63.                 exit(1);
  64.         }
  65.  
  66.                 /* Terminiamo il nome del file con NULL e se ultimo carattere è \n o \r lo cambiamo con \0*/
  67.                 filename[rc] = '\0';
  68.         if (filename[strlen(filename)-1] == '\n')
  69.                 filename[strlen(filename)-1] = '\0';
  70.         if (filename[strlen(filename)-1] == '\r')
  71.                 filename[strlen(filename)-1] = '\0';
  72.  
  73.         fprintf(stderr, "Ricevuta richiesta di inviare il file: '%s'\n", filename);
  74.  
  75.         /* open the file to be sent */
  76.         fd = open(filename, O_RDONLY);
  77.                 if (fd == -1) {
  78.                 fprintf(stderr, "Impossibile aprire '%s': %s\n", filename, strerror(errno));
  79.                 exit(1);
  80.         }
  81.  
  82.         /* get the size of the file to be sent */
  83.         fstat(fd, &stat_buf);
  84.         fsize = stat_buf.st_size;
  85.         bytes_sent = send(DescrittoreClient, &fsize, sizeof(fsize), 0);
  86.         if(bytes_sent == -1){
  87.                 print("Errore durante l'invio della grandezza del file\n");
  88.                 close(DescrittoreClient);
  89.                         close(fd);
  90.                         close(DescrittoreServer);
  91.                 exit(1);
  92.         }
  93.         /* copy file using sendfile */
  94.         offset = 0;
  95.         rc = sendfile(DescrittoreClient, fd, &offset, stat_buf.st_size);
  96.         if (rc == -1) {
  97.                 fprintf(stderr, "Errore durante l'invio di: '%s'\n", strerror(errno));
  98.                 exit(1);
  99.         }
  100.         if (rc != stat_buf.st_size) {
  101.                 fprintf(stderr, "Trasferimento incompleto: %d di %d bytes\n", rc, (int)stat_buf.st_size);
  102.                 exit(1);
  103.         }
  104.                 char *ip_address = inet_ntoa(cli_addr.sin_addr); /* inet_ntoa converte un hostname in un ip */
  105.                 printf("IP del client: %s\n", ip_address);             
  106.  
  107.                 close(DescrittoreClient);
  108.                 close(fd);
  109.         }
  110.         close(DescrittoreServer);
  111.         return EXIT_SUCCESS;
  112. }



Come funziona questo programma?
1) client manda nome file al server
2) server manda grandezza file al client
3) server manda il file
4) il client riceve il file

Qual è il problema?
Per esempio sto cercando di copiare un file "prova.txt" grande 2143 bytes, il client riceve la grandezza (2143) e quindi inzia a ricevere il file solo che il client "si blocca" in modalità ricezione e consuma MOLTA cpu! :grr:
Inoltre file ricevuto ha una grandezza di 95 byte :-|
Perchè accade ciò? :-?:-?

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6388
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 11:14
Martedì, 26/06/2012
A prima vista questi cicli

Codice sorgente - presumibilmente C/C++

  1. while(nread != bytes_read){
  2.                 while ((nread = read(DescrittoreClient, Buffer, sizeof(Buffer))) > 0){
  3.                         write(fd, Buffer, nread);
  4.                         tmp+=nread;
  5.                 }
  6.         }



non mi sembrano logicamente corretti.

Controlla ... può esistere un caso in cui il ciclo non termina mai?


Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 11:39
Mercoledì, 27/06/2012
Ciao!

Se ho letto bene nel primo ciclo while nel client cofronti nread con bytes_read, peró nread non sono i byte letti in totale ma solo quelli parziali dell'ultima chiamata a read, penso che tu debba usare la variabile tmp( che vedo hai già implementato).

Ciaociao

PM Quote
Avatar
polslinux (Normal User)
Newbie


Messaggi: 2
Iscritto: 25/06/2012

Segnala al moderatore
Postato alle 16:12
Domenica, 08/07/2012
Ho risolto sistemando i while loop :D

PM Quote