2010-11-22 5 views
2

J'ai la fonction suivante de configuration pour recevoir les données du serveur toutes les 2 minutes. Pour la première fois j'appelle la fonction, il semble fonctionner mais il se fige à l'appel recv qui ne revient jamais. et aurais-je besoin d'allouer le tampon sur chaque appel même si le serveur n'a rien à envoyer?recv trafic entrant du serveur

#define RCVBUFSIZE 32 

void Receive() 
{ 
    UINT totalBytesRcvd = 0, bytesRcvd = 0; 
    char buffer[RCVBUFSIZE];  /* Buffer for string */ 

    /* Receive up to the buffer size (minus 1 to leave space for 
    a null terminator) bytes from the sender */ 

    bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0); 

    if (bytesRcvd) 
    { 
     buffer[bytesRcvd] = '\0'; 
     MessageBox(0, buffer, 0, 0); //some way to display the received buffer 
    } 
    else if (bytesRcvd == SOCKET_ERROR) 
    { 
     return; 
    } 
} 
+2

Note: votre 'si (bytesRcvd)' 'chèque satisfait la SOCKET_ERROR' (qui est -1) état, ce qui signifie que vous allez essayer et d'écrire sur « tampon [-1] 's'il y a une erreur et Ensuite, continuez sur Bollock! –

Répondre

5

(1) Votre tampon n'est pas vraiment alloué, il réside sur la pile. Vous n'avez généralement pas besoin d'utiliser 32 octets sur la pile.

(2) recv est censé bloquer jusqu'à ce qu'il ait quelque chose à recevoir. Vous pouvez contourner cela en utilisant des sockets non bloquantes ou en utilisant select. S'il vous plaît voir here pour référence.

En particulier, vous pouvez

(2a) Utilisez ioctlsocket pour définir votre prise en mode non-bloquant. Ensuite, lorsque vous appelez read et qu'il n'y a rien à lire, vous obtiendrez l'erreur EWOULDBLOCK.

unsigned long non_blocking = 1; 
ioctlsocket (sockClient, FIONBIO, &non_blocking); 

lecture devient alors

bytesRcvd = recv(sockClient, buffer, RCVBUFSIZE - 1, 0); 
if (bytesRcvd == -1) { 
    if (WSAGetLastError() == EWOULDBLOCK) { 
     // nothing to read now 
    } else { 
     // an actual error occurred 
    } 
} else { 
    // reading was successful. Call to MsgBox here 
} 

(2b) Ou, vous pouvez appeler select pour déterminer s'il y a des données à lire, avant d'appeler effectivement read.

struct timeval timeout; 
timeout.tv_usec = 0; 
timeout.tv_sec = 0; 

fd_set r; 
FD_ZERO (&r); 
FD_SET (sockClient, &r); 
switch (select (sockClient + 1, &r, NULL, NULL, &timeout)) { 
    case -1: 
     // error 
     break; 
    case 0: 
     // nothing to read 
     break; 
    case 1: 
     // you may call read() 
     break; 
} 
+1

+1, bonne réponse. Il est également intéressant de noter que vous pouvez passer 'MSG_PEEK' à recv() pour vérifier s'il y a des octets disponibles à lire. –

+0

Si j'allais avec (2b) alors vous n'avez pas à pré-allouer ou déclarer tampon de toute taille sur la pile. mais vaut toujours la peine de marquer le socket comme non bloquant avec FIONBIO? – cnd

+0

Si vous n'êtes pas multithread (* et * avez un bug sérieux), le paramétrage ou non du paramètre 'FIONBIO' ne devrait pas faire de différence lors de l'utilisation du multiplexage 'select'. – dennycrane