2010-07-27 10 views
6

Tengo un problema en mi bucle recv() para winsock. Estoy tratando de terminar el ciclo cuando iResult == 0, sin embargo, el ciclo solo finaliza cuando el socket se cierra. Parece estar colgando en el último recv() donde iResult equivaldría a 0. Entonces, ¿hay alguna idea sobre cómo terminar el ciclo de forma efectiva? Mi objetivo final (ya sea que iResult == 0 o no, tal vez estoy haciendo esto de la manera incorrecta) es detener el ciclo cuando se ha leído toda la información enviada. Aquí está el bucle.Finalizando el ciclo "recv()" cuando se lee toda la información usando Winsock

do 
    { 
     iResult = recv(socket, recvbuf, BUFLEN-1, 0); 
     if(iResult > 0){ 
      // Null byte :) 
      // Remove that garbage >:(
      recvbuf[iResult] = '\0'; 
      printf("Recvbuf: %s\n\n\niResult: %d\n",recvbuf,iResult); 
      continue; // working properly 
     } 
     else if(iResult == 0) 
      // Connection closed properly 
      break; 
     else 
     { 
      printf("ERROR! %ld",WSAGetLastError()); 
      break; 
     } 
    } while(iResult > 0); 

Como dije, recibo todos los datos, simplemente no puedo salir del ciclo. El siguiente paso sería volver a escribir los datos en el servidor, pero se cuelga aquí hasta que se agote el tiempo de espera de ping. Socket es SOCK_STREAM y buflen se define como 0x200

Gracias

Respuesta

4

Por defecto, en lugar de devolver 0, recvblocks if there's no data to receive:

Si no hay datos de entrada está disponible en el zócalo, la llamada se bloquea recv y espera a que lleguen los datos de acuerdo con las reglas de bloqueo definidas para WSARecv con el indicador MSG_PARTIAL no establecido en a menos que el socket sea no bloqueante. En este caso, un valor de SOCKET_ERROR es devuelto con el código de error establecido en WSAEWOULDBLOCK. Las funciones de seleccionar, WSAAsyncSelect o WSAEventSelect se pueden usar para determinar cuando llegan más datos.

Puede utilizar ioctlsocket a colocar el conector de no-bloqueo:

u_long iMode = 1; 
ioctlsocket(socket, FIONBIO, &iMode); 

EDITAR: Aquí está la sugerencia setsockopt que hice en un rev anterior, luego se retira (ver comentarios):

puede utilizar la función setsockopt con la opción de establecer SO_RCVTIMEO el socket al tiempo de espera en recv si no hay datos disponibles.

+0

Quiero mantenerlo bloqueado para que pueda leer los datos, ¡pero su sugerencia de setsockopt() funcionó a la perfección! ¡Muchas gracias! – RageD

+0

@Dennis M .: Gracias. Había eliminado la sugerencia de 'setsockopt' a favor de usar' ioctlsocket' en su lugar, pero cualquiera de ellos debería funcionar. He editado 'setsockopt' en la respuesta. –

1

Al diseñar un mecanismo de comunicación TCP, debe definir los límites del mensaje. (a menudo, \ r \ n). En sí mismo, tcp no sabe acerca de los límites; tienes que hacer esto tú mismo. Es posible que la llamada a recv() no siempre regrese en un límite de mensaje. Un envío() puede dividirse en múltiples recv() - s en el otro extremo.

+2

Por el contrario, el envío múltiple() puede dar como resultado un solo recv() también. –

+0

buena aclaración: puede que no haya una correspondencia uno a uno entre send() y recv(). Sin embargo, la mayoría de las veces parece que send() causa un recv() !. Esto a veces confunde a las personas cuando su aplicación falla bajo una gran carga. – seand

Cuestiones relacionadas