Función recv (winsock.h)

La función recv recibe datos de un socket conectado o de un socket sin conexión enlazado.

Sintaxis

int recv(
  [in]  SOCKET s,
  [out] char   *buf,
  [in]  int    len,
  [in]  int    flags
);

Parámetros

[in] s

Descriptor que identifica un socket conectado.

[out] buf

Puntero al búfer para recibir los datos entrantes.

[in] len

Longitud, en bytes, del búfer al que apunta el parámetro buf .

[in] flags

Conjunto de marcas que influye en el comportamiento de esta función. Vea los comentarios más abajo. Consulte la sección Comentarios para obtener más información sobre el valor posible de este parámetro.

Valor devuelto

Si no se produce ningún error, recv devuelve el número de bytes recibidos y el búfer al que apunta el parámetro buf contendrá estos datos recibidos. Si la conexión se ha cerrado correctamente, el valor devuelto es cero.

De lo contrario, se devuelve un valor de SOCKET_ERROR y se puede recuperar un código de error específico llamando a WSAGetLastError.

Código de error Significado
WSANOTINITIALISED
Debe producirse una llamada de WSAStartup correcta antes de usar esta función.
WSAENETDOWN
Error en el subsistema de red.
WSAEFAULT
El parámetro buf no está completamente incluido en una parte válida del espacio de direcciones del usuario.
WSAENOTCONN
El socket no está conectado.
WSAEINTR
La llamada (bloqueo) se canceló a través de WSACancelBlockingCall.
WSAEINPROGRESS
Una llamada de Bloqueo de Windows Sockets 1.1 está en curso o el proveedor de servicios sigue procesando una función de devolución de llamada.
WSAENETRESET
En el caso de un socket orientado a la conexión, este error indica que la conexión se ha interrumpido debido a la actividad de mantenimiento activo que detectó un error mientras la operación estaba en curso. Para un socket de datagrama, este error indica que expiró el tiempo de vida.
WSAENOTSOCK
El descriptor no es un socket.
WSAEOPNOTSUPP
MSG_OOB se especificó, pero el socket no es de estilo de flujo, como el tipo SOCK_STREAM, los datos OOB no se admiten en el dominio de comunicación asociado a este socket o el socket es unidireccional y solo admite operaciones de envío.
WSAESHUTDOWN
El socket se ha apagado; no es posible recibir en un socket después de que se haya invocado el apagado con el modo establecido en SD_RECEIVE o SD_BOTH.
WSAEWOULDBLOCK
El socket se marca como no desbloqueado y la operación de recepción se bloquearía.
WSAEMSGSIZE
El mensaje era demasiado grande para caber en el búfer especificado y se truncó.
WSAEINVAL
El socket no se ha enlazado con el enlace, o se especificó una marca desconocida, o MSG_OOB se especificó para un socket con SO_OOBINLINE habilitado o (solo para sockets de flujo de bytes) len era cero o negativo.
WSAECONNABORTED
Se finalizó el circuito virtual debido a un tiempo de espera agotado u otro error. La aplicación debería cerrar el socket porque ya no se puede usar.
WSAETIMEDOUT
Se interrumpió la conexión debido a un error de red o porque el sistema del mismo nivel no respondió.
WSAECONNRESET
El lado remoto que ejecuta un cierre firme o de anulación restableció el circuito virtual. La aplicación debería cerrar el socket porque ya no se puede usar. En un socket UDP-datagram, este error indicaría que una operación de envío anterior dio lugar a un mensaje ICMP "Puerto inaccesible".

Comentarios

La función recv se usa para leer datos entrantes en sockets orientados a la conexión o sockets sin conexión. Cuando se usa un protocolo orientado a la conexión, los sockets deben estar conectados antes de llamar a recv. Al usar un protocolo sin conexión, los sockets deben enlazarse antes de llamar a recv.

La dirección local del socket debe conocerse. Para las aplicaciones de servidor, use una función de enlace explícita o una función de aceptación implícita o WSAAccept . No se recomienda el enlace explícito para las aplicaciones cliente. En el caso de las aplicaciones cliente, el socket se puede enlazar implícitamente a una dirección local mediante connect, WSAConnect, sendto, WSASendTo o WSAJoinLeaf.

En el caso de los sockets conectados o sin conexión, la función recv restringe las direcciones desde las que se aceptan los mensajes recibidos. La función solo devuelve mensajes de la dirección remota especificada en la conexión. Los mensajes de otras direcciones se descartan (silenciosamente).

En el caso de los sockets orientados a la conexión (tipo SOCK_STREAM por ejemplo), la llamada a recv devolverá tantos datos como esté disponible actualmente, hasta el tamaño del búfer especificado. Si el socket se ha configurado para la recepción en línea de datos OOB (opción de socket SO_OOBINLINE) y los datos de OOB aún no están leídos, solo se devolverán los datos de OOB. La aplicación puede usar el comando ioctlsocket o WSAIoctlSIOCATMARK para determinar si se van a leer más datos OOB.

En el caso de los sockets sin conexión (tipo SOCK_DGRAM u otros sockets orientados a mensajes), los datos se extraen del primer datagrama (mensaje) en cola de la dirección de destino especificada por la función connect .

Si el datagrama o mensaje es mayor que el búfer especificado, el búfer se rellena con la primera parte del datagrama y se vuelve a generar el error WSAEMSGSIZE. En el caso de los protocolos no confiables (por ejemplo, UDP), se pierden los datos excesivos; para protocolos confiables, el proveedor de servicios conserva los datos hasta que se lee correctamente llamando a recv con un búfer lo suficientemente grande.

Si no hay datos entrantes disponibles en el socket, la llamada de recv bloquea y espera a que los datos lleguen según las reglas de bloqueo definidas para WSARecv con la marca de MSG_PARTIAL no establecida a menos que el socket no esté desbloqueado. En este caso, se devuelve un valor de SOCKET_ERROR con el código de error establecido en WSAEWOULDBLOCK. Las funciones select, WSAAsyncSelect o WSAEventSelect se pueden usar para determinar cuándo llegan más datos.

Si el socket está orientado a la conexión y el lado remoto ha apagado correctamente la conexión y se han recibido todos los datos, un recv se completará inmediatamente con cero bytes recibidos. Si se ha restablecido la conexión, se producirá un error en un recv con el error WSAECONNRESET.

El parámetro flags se puede usar para influir en el comportamiento de la invocación de función más allá de las opciones especificadas para el socket asociado. La semántica de esta función viene determinada por las opciones de socket y el parámetro flags . El valor posible del parámetro flags se construye mediante el operador OR bit a bit con cualquiera de los valores siguientes.

Valor Significado
MSG_PEEK Observa los datos entrantes. Los datos se copian en el búfer, pero no se quitan de la cola de entrada.
MSG_OOB Procesa datos fuera de banda (OOB).
MSG_WAITALL La solicitud de recepción solo se completará cuando se produzca uno de los siguientes eventos:
  • El búfer proporcionado por el autor de la llamada está completamente lleno.
  • Se cerró la conexión.
  • Se ha cancelado la solicitud o se ha producido un error.
Tenga en cuenta que si el transporte subyacente no admite MSG_WAITALL o si el socket está en modo de no bloqueo, se producirá un error en esta llamada con WSAEOPNOTSUPP. Además, si se especifica MSG_WAITALL junto con MSG_OOB, MSG_PEEK o MSG_PARTIAL, se producirá un error en esta llamada con WSAEOPNOTSUPP. Esta marca no se admite en sockets de datagramas o sockets orientados a mensajes.
 
Nota Al emitir una llamada de Winsock de bloqueo como recv, Winsock puede que tenga que esperar a un evento de red antes de que se pueda completar la llamada. Winsock realiza una espera alertable en esta situación, que se puede interrumpir mediante una llamada de procedimiento asincrónica (APC) programada en el mismo subproceso. La emisión de otra llamada winsock de bloqueo dentro de un APC que interrumpió una llamada de Winsock de bloqueo en curso en el mismo subproceso provocará un comportamiento indefinido y los clientes winsock nunca deben intentarlo.
 

Código de ejemplo

En el ejemplo de código siguiente se muestra el uso de la función recv .
#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

int __cdecl main() {

    //----------------------
    // Declare and initialize variables.
    WSADATA wsaData;
    int iResult;

    SOCKET ConnectSocket = INVALID_SOCKET;
    struct sockaddr_in clientService; 

    char *sendbuf = "this is a test";
    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;
  
    //----------------------
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR) {
      printf("WSAStartup failed: %d\n", iResult);
      return 1;
    }

    //----------------------
    // Create a SOCKET for connecting to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port of the server to be connected to.
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
    clientService.sin_port = htons( 27015 );

    //----------------------
    // Connect to server.
    iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
    if ( iResult == SOCKET_ERROR) {
        closesocket (ConnectSocket);
        printf("Unable to connect to server: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
    if (iResult == SOCKET_ERROR) {
        printf("send failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if ( iResult > 0 )
            printf("Bytes received: %d\n", iResult);
        else if ( iResult == 0 )
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());

    } while( iResult > 0 );

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}


Código de ejemplo

Para obtener más información y otro ejemplo de la función recv, consulte Introducción With Winsock.

Windows Phone 8: esta función es compatible con las aplicaciones de Windows Phone Store en Windows Phone 8 y versiones posteriores.

Windows 8.1 y Windows Server 2012 R2: esta función es compatible con las aplicaciones de la Tienda Windows en Windows 8.1, Windows Server 2012 R2 y versiones posteriores.

Requisitos

   
Cliente mínimo compatible Windows 8.1, Windows Vista [aplicaciones de escritorio | Aplicaciones para UWP]
Servidor mínimo compatible Windows Server 2003 [aplicaciones de escritorio | aplicaciones para UWP]
Plataforma de destino Windows
Encabezado winsock.h (incluya Winsock2.h)
Library Ws2_32.lib
Archivo DLL Ws2_32.dll

Consulte también

WSAAsyncSelect

WSARecv

WSARecvEx

Funciones winsock

Referencia de Winsock

recvfrom

select

enviar

socket