trasferimento di file tramite socket, dimensione finale con meno bytes
-
22-08-2019 - |
Domanda
Sto cercando di ricevere qualche file tramite prese in C. Ma il server mi manda pacchetti da 64 byte per un file 1000000 byte per esempio e ottengo circa 999902 byte sul file di destinazione.
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);
Quando viene utilizzato tramite un socket TCP / IP locale funziona, ma non in una connessione lenta. Vedo attraverso il debug che ho un sacco di 64 blocchi di byte, e un pezzo di 30 byte nei pressi di EOF. So che si può ottenere meno byte su read () in quanto la chiamata ritorna quando tutti i dati (> 1 byte) è disponibile. Ma questa condizione non dovrebbe essere catturato dal tempo? Deve restituire quando n == 0, che sono più dati (EOF).
Thx per il vostro aiuto.
(EDIT)
L'invio di codice come segue:
while (n=read(file_fd, buffer, BUFSIZE))
{
write (sdaccept, buffer, n)
}
So che entrambi read () e write () può restituire N (EDIT II) Testato con una sorgente C con 10673 byte, riceve 10575 senza corruzione, se non che il file di destinazione manca dei primi 98 byte !!!
Soluzione
Il codice di invio fornito ignora il fatto che scrivere () (o send ()) su un socket non è obbligato a scrivere l'intero buffer.
write () / send () potrebbe decidere di scrivere 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 una connessione lenta.
Il lato invio dovrebbe controllare il valore di ritorno di write () per rilevare la quantità di dati è stato effettivamente scritto e regolare di conseguenza.
Scrivi 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 );
}