2009-03-26 12 views
6

Sto provando a ricevere un file tramite i socket in C. Ma il server mi invia pacchetti a 64 byte per un file da 1000000 byte per esempio e ottengo circa 999902 byte sul file di destinazione.Trasferimento file tramite socket, dimensione finale con meno byte

while ((n = read(sd, buffer_in, BUFSIZE))) // BUFSIZE = 64 
{ 
    if(n<0) 
    { 
     printf("Fail.\n"); 
     fclose(archivo); 
     return -1; 
    } 

    if(fwrite(buffer_in, n, 1, f) !=1) 
    { 
     printf("fwrite error.\n"); 
     fclose(archivo); 
     return -1; 
    } 

    bytes+=n; 
} 

printf("We received %d bytes", bytes); 

Se utilizzato tramite un socket TCP/IP locale funziona, ma non in una connessione lenta. Vedo attraverso il debugging che ottengo molti pezzi da 64 byte e un chunk da 30 byte vicino a EOF. So che è possibile ottenere meno byte su read() poiché la chiamata ritorna quando sono disponibili dati (> 1 byte). Ma questa condizione non dovrebbe essere catturata nel frattempo? Dovrebbe tornare quando n == 0, cioè non ci sono più dati (EOF).

Thx per il vostro aiuto.

(EDIT)

Invio codice come segue:

while (n=read(file_fd, buffer, BUFSIZE)) 
{ 
    write (sdaccept, buffer, n) 
} 

So che entrambi read() e write() possono restituire N < BUFSIZE, ma non dovrebbe questo ciclo di lavoro che di conseguenza ? Ho aggiunto n e restituisce 1000000, la dimensione esatta.

(EDIT II)

testato con una sorgente C con 10673 byte, riceve 10575 senza corruzione, tranne che il file di destinazione manca dei primi 98 byte !!!

+0

Circa 999.902? O esattamente? – paxdiablo

+0

Non vedo difetti evidenti in questo codice - si prega di mostrare anche il codice di invio. – Alnitak

+0

particolarmente dispari, poiché 64 si divide in 1000000 esattamente –

risposta

11

Il codice di invio fornito ignora il fatto che write() (o send()) su un socket non è obbligato a scrivere l'intero buffer.

write()/send() potrebbe decidere di scriverlo parzialmente o non scrivere affatto se il sottosistema sottostante rifiuta di ricevere più dati (ad esempio il sottosistema di rete può avere una coda per i dati da inviare e questa coda è già pieno). Questo è altamente probabile su una connessione lenta.

Il lato di invio deve controllare il valore di ritorno di write() per rilevare quanti dati sono stati effettivamente scritti e regolare di conseguenza.

scrittura dovrebbe essere fatto in qualche modo simile a questo:

int readAmount; 
while(readAmount = read(file_fd, buffer, BUFSIZE) > 0) 
{ 
    int totalWritten = 0; 
    do { 
     int actualWritten; 
     actualWritten = write (sdaccept, buffer + totalWritten, readAmount - totalWritten); 
     if(actualWritten == - 1) { 
      //some error occured - quit; 
     } 
     totalWritten += actualWritten; 
    } while(totalWritten < readAmount); 
} 
+0

Invio del codice lato aggiunto. –

+0

L'invio del codice è soggetto esattamente al problema che ho descritto. Aggiunta correzione suggerita. – sharptooth

+0

Trasferimenti ancora 999902 byte !!!! :(:( –

Problemi correlati