A transferência de arquivos através de sockets, o tamanho final com menos bytes
-
22-08-2019 - |
Pergunta
Eu estou tentando receber algum arquivo através de sockets em C. Mas o servidor me envia pacotes de 64 bytes para um arquivo 1000000 byte, por exemplo, e eu recebo cerca de 999902 bytes no arquivo de destino.
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 usado através de um TCP / IP local soquete que funciona, mas não em uma conexão lenta. Eu vejo através de depuração que eu recebo um monte de 64 pedaços de bytes, e um pedaço de 30 byte perto EOF. Eu sei que você pode obter menos bytes em read () desde a chamada retorna quando todos os dados (> 1 byte) está disponível. Mas esta condição não deve ser catched pelo tempo? Deve retornar quando n == 0, que há mais dados (EOF).
Thx pela ajuda.
(EDIT)
código de envio da seguinte forma:
while (n=read(file_fd, buffer, BUFSIZE))
{
write (sdaccept, buffer, n)
}
Eu sei que tanto read () e write () pode retornar N (EDIT II) Testado com uma fonte C com 10673 bytes, recebe 10575 sem corrupção, exceto que o arquivo de destino não tem a primeira 98 bytes !!!
Solução
O código de envio fornecido ignora o fato de que write () (ou send ()) em um soquete não é obrigado a escrever todo o buffer.
write () / send () pode decidir escrevê-lo parcialmente ou não escrever em tudo se o subsistema subjacente se recusa a receber mais dados (por exemplo, o subsistema de rede pode ter uma fila para os dados a enviar e esta fila já está cheio). Isso é altamente provável em uma conexão lenta.
O lado de envio deve verificar o valor de retorno de write () para detectar a quantidade de dados foi realmente escrito e ajustar em conformidade.
Write deve ser feito de alguma forma como este:
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 );
}