Lidando com send() parciais
Lembra da seção sobre send() quando eu disse que
este pode não enviar todos os bytes que você pediu?
Ou seja, você quer enviar 512 bytes, mas retorna 412. O
que aconteceu com os outros 100 bytes?
Bem, eles ainda estão no buffer esperando serem
enviados. Devido a circunstâncias além do seu
controle, o kernel decidiu não enviar os dados de uma
vez, e agora meu amigo, cabe a você enviá-los.
Você poderia escrever uma função com esta
para fazer isso:
int enviatudo (int s , char *buff, int *len)
{
int total = 0 ; // quantos bytes enviamos?
int bytes_resta = *len; // quantos ainda restam para enviar
int n;
while ( total < *len) {
n = send (s, buf+total, bytes_resta, 0);
if ( n == -1 ) { break; }
total += n;
bytes_resta -= n;
}
*len = total; // retorna o número que realmente foi
enviado
return n==-1?-1: 0; // retorna -1 em caso de falha, 0 caso
sucesso
}
Nesse exemplo, s é o socket para onde você quer
enviar os dados, buf é o buffer contendo os dados, e len
é um ponteiro para um int contendo o número de
bytes no buffer.
A função retorna -1 caso ocorra erro. Além
disso, o número de bytes realmente enviados é
retornado em len. Isso será o mesmo número de bytes
que você pediu para enviar, contanto que não ocorra
erro. enviatudo() vai fazer o possível para enviar os
dados , mas caso ocorra erro, ela retorna para você
imediatamente.
Para completar , aqui está um exemplo de chamada para
esta função:
char buf[10] = "Hrerer!";
int len;
len = strlen (buf);
if (enviatudo ( s, buf, &len) == -1) {
perror ("enviatudo");
printf ("Nós somente enviamos %d bytes porque houve
erro!!\n", len);
}
O que acontece no lado do receptor quando parte do pacote
chega? Se os pacotes são de tamanhos variáveis,
como o receptor sabe quando um pacote termina e outro
começa? Sim , cenários reais são chatos assim.
Você provavelmente vai ter que empacotar (lembra-se da
seção sobre encapsulamento no começo do
documento?) Continue lendo para mais detalhes.