Come sapere quale caso si verifica quando recv non bloccante restituisce 0?
Ho un semplice server TCP che funziona con socket non bloccanti.
Citazione dalla manpage di recv;
Quando un peer stream socket ha eseguito un arresto ordinato, il valore restituito sarà 0 (il tradizionale ritorno "end-of-file").
Il valore 0 può anche essere restituito se il numero richiesto di byte da ricevere da uno stream socket era 0.
Quando il socket è leggibile, lo leggo con questo codice:
uint8_t buf[2048];
ssize_t rlen;
while(1){
rlen = recv(fd, buf, sizeof(buf), 0);
if(rlen < 0){
/* some error came, let's close socket... */
}
else if(rlen == 0){
/* is there no bytes to read? do we need break; in here? */
/* is socket closed by peer? do we need to close socket? */
}
/* some code that process buf and rlen... */
}
Come possiamo sapere quale caso accade quando recv
restituisce 0?
Risposte
Quando recv
restituisce 0 significa che il socket è stato chiuso con garbo dall'altro peer e può essere chiuso anche dalla tua parte. Quando non sono presenti dati nel socket, viene restituito -1 ed errnoè impostato su EAGAIN
/ ETIMEDOUT
e il socket non deve essere chiuso.
Infine, quando -1 viene restituito ed errno
è impostato su un valore diverso da EWOULDBLOCK
o EAGAIN
il socket deve essere chiuso, perché si è verificato un errore irreversibile.
Per i socket non bloccanti significa che nessun dato è immediatamente disponibile quando recv
viene chiamato. Per i socket bloccanti) significa tgat nessun dato è disponibile anche dopo il timeout ( SO_RCVTIMEO
) precedentemente impostato con setsockopt()
scaduto.
Come hai citato correttamente nella tua ultima modifica, 0 può essere restituito recv
anche se la dimensione richiesta è 0.
Come possiamo sapere quale caso accade quando recv restituisce 0?
Basta testare la dimensione recv fornita (in questo caso è la dimensione di un array costante, quindi non ha molto senso; ma nel caso sia una variabile proveniente da altrove ...):
bufSize = sizeof(buf);
/* further code that, who knows, might affect bufSize */
rlen = read(fd, buf, bufSize);
if(rlen < 0){
if (errno != ETIMEDOUT && errno != EWOLUDBLOCK)
{
/* some error came, let's close socket... */
}
}
else if(rlen == 0){
if (bufSize != 0)
{
/* Close socket */
}
}