2009-01-13 7 views
4

Sous-jacente à la pile de transport TCP se trouvent un certain nombre de limites de mémoire tampon, parfois documentées par leurs auteurs. Sur WinXP SP3, je suis tombé sur l'un d'entre eux, je pense, et je n'arrive pas à comprendre pourquoi.Pourquoi le recv échoue-t-il lorsque la taille de la mémoire tampon demandée est supérieure à la quantité de données disponibles?

J'ai implémenté un client simple pour obtenir des données d'un serveur (écrit par un collègue en Java). Le protocole consiste à écrire la longueur des données (dans l'ordre du réseau) en quatre octets, puis les données. Le serveur écrit les données dans le flux TCP dans des blocs de 1024 octets. Le client reçoit correctement la longueur de la mémoire tampon de données, alloue de la mémoire et appelle à plusieurs reprises recv dans une boucle pour obtenir toutes les données:

unsigned int TCP_BlockSize = 4096; 
unsigned int len; 
int result; 

...code to request len... 
unsigned char *buf = new unsigned char[len]; 

if(len > TCP_BlockSize) 
{ 
Uint32 currentLen = 0; 
result = 0; 
Uint32 failCount = 0; 
while(currentLen < len && result >= 0) 
{ 
     result = recv(sock, buf + currentLen, TCP_BlockSize); 
     if(result > 0) 
    { 
     currentLen = currentLen + result; 
    } 
    else 
     { 
    break; 
     } 
} 
} 

Si je mets TCP_BlockSize à 4095 ou au-dessous, tout est bon et je peux recevoir transmissions multi-mégaoctets. Lorsque j'essaie 4096 blocs de réception de taille, la dernière requête pour les données restantes, qui est len ​​- currentLen < TCP_BlockSize, échoue toujours avec une valeur de retour de -1, et errno = 0. J'ai essayé quelques expériences comme la taille de la taille données transmises et quelque part entre 815054 et 834246 octets tout va boom pour les blocs de réception 4096 octets.

Un autre détail: le serveur ferme le socket après l'envoi du dernier octet. Ce qui soulève la question, pourquoi les données restantes ne seraient pas retournées? Il se sent comme un défaut de ne pas retourner -1 de recv jusqu'à ce que le flux est alors vide et fermé, car il est ambigu lorsque le flux n'est pas vide et fermé pour recevoir -1 à partir de recv.

Alors, comment puis-je obtenir la dernière donnée?

+0

La réponse de Nicolas Mancuso est correcte et résout le problème. Merci! –

Répondre

2

Essayez quelque chose comme ...

to_rcv = (len - currentlen < TCP_BlockSize) ? len - currentlen : TCP_BlockSize; 
result = recv(sock, buf + currentLen, to_rcv); 

De cette façon recv finale ne demandera le montant nécessaire, sinon il va demander le TCP_BlockSize.

Questions connexes