A transferência de arquivos através de sockets, o tamanho final com menos bytes

StackOverflow https://stackoverflow.com/questions/684733

  •  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 !!!

Foi útil?

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 );
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top