Función de devolución de llamada LPWSPRECV (ws2spi.h)

La función LPWSPRecv recibe datos en un socket.

Sintaxis

LPWSPRECV Lpwsprecv;

int Lpwsprecv(
  [in]         SOCKET s,
  \[in\, out\] LPWSABUF lpBuffers,
  [in]         DWORD dwBufferCount,
  [out]        LPDWORD lpNumberOfBytesRecvd,
  \[in\, out\] LPDWORD lpFlags,
  [in]         LPWSAOVERLAPPED lpOverlapped,
  [in]         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  [in]         LPWSATHREADID lpThreadId,
  [out]        LPINT lpErrno
)
{...}

Parámetros

[in] s

Descriptor que identifica un socket conectado.

\\[in\\, out\\] lpBuffers

Puntero a una matriz de estructuras WSABUF . Cada estructura WSABUF contiene un puntero a un búfer y la longitud del búfer, en bytes.

[in] dwBufferCount

Número de estructuras WSABUF en la matriz lpBuffers .

[out] lpNumberOfBytesRecvd

Puntero al número de bytes recibidos por esta llamada.

\\[in\\, out\\] lpFlags

Puntero a marcas que especifican la forma en que se realiza la llamada.

[in] lpOverlapped

Puntero a una estructura WSAOverlapped (se omite para estructuras no superpuestas).

[in] lpCompletionRoutine

Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Puntero a la rutina de finalización a la que se llama cuando se ha completado la operación de recepción (se omite para estructuras no superpuestas).

[in] lpThreadId

Puntero a una estructura WSATHREADID que va a usar el proveedor en una llamada posterior a WPUQueueApc. El proveedor debe almacenar la estructura WSATHREADID a la que se hace referencia (no el puntero a la misma) hasta que se devuelva la función WPUQueueApc .

[out] lpErrno

Puntero al código de error.

Valor devuelto

Si no se produce ningún error y la operación de recepción se ha completado inmediatamente, LPWSPRecv devuelve cero. Tenga en cuenta que, en este caso, la rutina de finalización, si se especifica, ya se habrá puesto en cola. De lo contrario, se devuelve un valor de SOCKET_ERROR y hay disponible un código de error específico en lpErrno. El código de error WSA_IO_PENDING indica que la operación superpuesta se ha iniciado correctamente y que la finalización se indicará más adelante. Cualquier otro código de error indica que no se inició ninguna operación superpuesta y no se producirá ninguna indicación de finalización.

Código de error Significado
WSAENETDOWN
Error en el subsistema de red.
WSAENOTCONN
socket no conectado.
WSAEINTR
(Bloqueo) la llamada se canceló a través de LPWSPCancelBlockingCall.
WSAEINPROGRESS
El bloqueo de la llamada a Windows Sockets está en curso o el proveedor de servicios sigue procesando una función de devolución de llamada.
WSAENETRESET
Se ha interrumpido la conexión debido a que la actividad para mantener activa la conexión detectó un error durante la operación.
WSAEFAULT
El parámetro lpBuffers no está totalmente incluido en una parte válida del espacio de direcciones del usuario.
WSAENOTSOCK
El descriptor no es un socket.
WSAEOPNOTSUPP
MSG_OOB se especificó, pero el socket no es de 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
Se ha apagado el socket; no es posible recibir a través de LPWSPRecv en un socket después de que LPWSPShutdown se haya invocado con cómo se establece en SD_RECEIVE o SD_BOTH.
WSAEWOULDBLOCK
Windows NT: sockets superpuestos: hay demasiadas solicitudes de E/S superpuestas pendientes. Sockets no superpuestos: el socket se marca como no desbloqueado y la operación de recepción no se puede completar inmediatamente.
WSAEMSGSIZE
El mensaje era demasiado grande para caber en el búfer especificado y (solo para protocolos no confiables) se ha descartado cualquier parte final del mensaje que no cabe en el búfer.
WSAEINVAL
El socket no se ha enlazado (por ejemplo, con LPWSPBind) o el socket no se crea con la marca superpuesta.
WSAECONNABORTED
El circuito virtual finalizó debido a un tiempo de espera u otro error.
WSAECONNRESET
El circuito virtual se restableció por el lado remoto.
WSAEDISCON
Socket s está orientado a mensajes y el circuito virtual se cerró correctamente por el lado remoto.
WSA_IO_PENDING
Una operación superpuesta se inició correctamente y la finalización se indicará en un momento posterior.
WSA_OPERATION_ABORTED
La operación superpuesta se ha cancelado debido al cierre del socket.

Comentarios

LPWSPRecv se usa en sockets conectados o sockets sin conexión enlazados especificados por el parámetro s y se usa para leer los datos entrantes. La dirección local del socket debe conocerse. Esto puede hacerse explícitamente a través de LPWSPBind o implícitamente a través de LPWSPAccept, LPWSPConnect, LPWSPSendTo o LPWSPJoinLeaf.

En el caso de sockets conectados sin conexión, esta función restringe las direcciones de 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 superpuestos LPWSPRecv se usa para publicar uno o varios búferes en los que se colocarán los datos entrantes a medida que estén disponibles, después de lo cual se produce la indicación de finalización especificada por el cliente SPI de Windows Sockets (invocación de la rutina de finalización o configuración de un objeto de evento). Si la operación no se completa inmediatamente, el estado de finalización final se recupera a través de la rutina de finalización o LPWSPGetOverlappedResult.

Si lpOverlapped y lpCompletionRoutine son null, el socket de esta función se tratará como un socket no superpuesto.

En el caso de los sockets no superpuestos, se omiten los parámetros lpOverlapped, lpCompletionRoutine y lpThreadId . Los datos que ya se hayan recibido y almacenado en búfer por el transporte se copiarán en los búferes de usuario proporcionados. En el caso de un socket de bloqueo sin datos recibidos y almacenados en búfer por el transporte, la llamada se bloqueará hasta que se reciban los datos. Windows Sockets 2 no define ningún mecanismo de tiempo de espera de bloqueo estándar para esta función. En el caso de los protocolos que actúan como protocolos de flujo de bytes, la pila intenta devolver tantos datos como sea posible sujeto al espacio de búfer proporcionado y a la cantidad de datos recibidos disponibles. Sin embargo, la recepción de un solo byte es suficiente para desbloquear el autor de la llamada. No hay ninguna garantía de que se devuelva más de un solo byte. En el caso de los protocolos que actúan como orientados a mensajes, se requiere un mensaje completo para desbloquear al autor de la llamada.

Si un protocolo actúa como secuencia de bytes viene determinado por la configuración de XP1_MESSAGE_ORIENTED y XP1_PSEUDO_STREAM en su estructura WSAPROTOCOL_INFO y el valor de la marca MSG_PARTIAL que se pasa a esta función (para los protocolos que lo admiten). Las combinaciones pertinentes se resumen en la tabla siguiente (un asterisco (*) indica que el valor de este bit no importa en este caso).

XP1_MESSAGE_ORIENTED XP1_PSEUDO_STREAM MSG_PARTIAL Actúa como
Sin establecer * * secuencia de bytes
* set * secuencia de bytes
set Sin establecer set secuencia de bytes
set Sin establecer Sin establecer orientado a mensajes

Los búferes proporcionados se rellenan en el orden en que aparecen en la matriz a la que apuntan lpBuffers, y los búferes se empaquetan para que no se creen agujeros.

La matriz de estructuras WSABUF a las que apunta el parámetro lpBuffers es transitoria. Si esta operación se completa de forma superpuesta, es responsabilidad del proveedor de servicios capturar esta matriz de punteros a estructuras WSABUF antes de volver de esta llamada. Esto permite a los clientes SPI de Windows Sockets compilar matrices WSABUF basadas en pila.

En el caso de los sockets de estilo de secuencia de bytes (por ejemplo, el tipo SOCK_STREAM), los datos entrantes se colocan en los búferes hasta que se rellenan los búferes, se cierra la conexión o se agotan los datos almacenados en búfer internamente. Independientemente de si los datos entrantes rellenan o no todos los búferes, la indicación de finalización se produce para sockets superpuestos. En el caso de los sockets orientados a mensajes (por ejemplo, tipo SOCK_DGRAM), se coloca un mensaje entrante en los búferes proporcionados, hasta el tamaño total de los búferes proporcionados y la indicación de finalización se produce para sockets superpuestos. Si el mensaje es mayor que los búferes proporcionados, los búferes se rellenan con la primera parte del mensaje. Si el proveedor de servicios admite la característica MSG_PARTIAL, la marca MSG_PARTIAL se establece en lpFlags y se pueden usar las operaciones de recepción posteriores para recuperar el resto del mensaje. Si no se admite MSG_PARTIAL pero el protocolo es confiable, LPWSPRecv genera el error WSAEMSGSIZE y se puede usar una operación de recepción posterior con un búfer mayor para recuperar todo el mensaje. De lo contrario, (es decir, el protocolo no es confiable y no admite MSG_PARTIAL), se pierden los datos excesivos y LPWSPRecv genera el error WSAEMSGSIZE.

En el caso de los sockets orientados a la conexión, LPWSPRecv puede indicar la terminación correcta del circuito virtual de una de dos maneras, dependiendo de si el socket es un flujo de bytes o orientado a mensajes. En el caso de las secuencias de bytes, cero bytes que se han leído indica un cierre correcto y que nunca se leerán más bytes. En el caso de los sockets orientados a mensajes, donde a menudo se permite un mensaje de bytes cero, se usa un código de error de devolución de WSAEDISCON para indicar un cierre correcto. En cualquier caso, se ha producido un código de error devuelto de WSAECONNRESET .

El parámetro lpFlags 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. Es decir, la semántica de esta función viene determinada por las opciones de socket y el parámetro lpFlags . Este último se construye mediante el operador OR bit a bit con cualquiera de los valores siguientes.

Valor Significado
MSG_PEEK Examina los datos entrantes. Los datos se copian en el búfer, pero no se quitan de la cola de entrada. Esta marca solo es válida para sockets no superpuestos.
MSG_OOB Procesa datos fuera de banda (OOB).
MSG_PARTIAL Esta marca es solo para sockets orientados a mensajes. En la salida, indica que los datos proporcionados son una parte del mensaje transmitido por el remitente. Las partes restantes del mensaje se proporcionarán en las operaciones de recepción posteriores. Una operación de recepción posterior con MSG_PARTIAL marca desactivada indica el final del mensaje del remitente. Como parámetro de entrada, MSG_PARTIAL indica que la operación de recepción debe completarse aunque solo el proveedor de servicios haya recibido parte de un mensaje.

Si una operación superpuesta se completa inmediatamente, LPWSPRecv devuelve un valor de cero y el parámetro lpNumberOfBytesRecvd se actualiza con el número de bytes recibidos y los bits de marca señalados por el parámetro lpFlags también se actualizan. Si la operación superpuesta se inicia correctamente y se completará más adelante, LPWSPRecv devuelve SOCKET_ERROR e indica el código de error WSA_IO_PENDING. En este caso, lpNumberOfBytesRecvd y lpFlags no se actualizan. Cuando la operación superpuesta completa la cantidad de datos transferidos se indica a través del parámetro cbTransferred en la rutina de finalización (si se especifica) o mediante el parámetro lpcbTransfer en LPWSPGetOverlappedResult. Los valores de marca se obtienen a través del parámetro dwFlags de la rutina de finalización o examinando el parámetro lpdwFlags de WSAGetOverlappedResult.

Los proveedores deben permitir que se llame a esta función desde dentro de la rutina de finalización de una función LPWSPRecv, LPWSPRecvFrom, LPWSPSend o LPWSPSendTo . Sin embargo, para un socket determinado, las rutinas de finalización de E/S no se pueden anidar. Esto permite que las transmisiones de datos sensibles al tiempo se produzcan por completo dentro de un contexto preferente.

El parámetro lpOverlapped debe ser válido durante la operación superpuesta. Si hay varias operaciones de E/S pendientes simultáneamente, cada una debe hacer referencia a una estructura superpuesta independiente. La estructura WSAOverlapped se define en su propia página de referencia.

Si el parámetro lpCompletionRoutine es null, el proveedor de servicios señala al miembro hEvent de lpOverlapped cuando se completa la operación superpuesta si contiene un identificador de objeto de evento válido. El cliente SPI de Windows Sockets puede usar LPWSPGetOverlappedResult para esperar o sondear en el objeto de evento.

Si lpCompletionRoutine no es null, el miembro hEvent se omite y el cliente SPI de Windows Sockets puede usarse para pasar información de contexto a la rutina de finalización. Un cliente que pasa un lpCompletionRoutine null y, posteriormente, llama a WSAGetOverlappedResult para la misma solicitud de E/S superpuesta no puede establecer el parámetro fWait para esa invocación de WSAGetOverlappedResult en TRUE. En este caso, el uso del miembro hEvent no está definido y al intentar esperar en el miembro hEvent se generarían resultados impredecibles.

Es responsabilidad del proveedor de servicios organizar la invocación de la rutina de finalización especificada por el cliente cuando se completa la operación superpuesta. Puesto que la rutina de finalización debe ejecutarse en el contexto del mismo subproceso que inició la operación superpuesta, no se puede invocar directamente desde el proveedor de servicios. El Ws2_32.dll ofrece un mecanismo de llamada a procedimiento asincrónico (APC) para facilitar la invocación de rutinas de finalización.

Un proveedor de servicios organiza para que una función se ejecute en el subproceso y el contexto de proceso adecuados mediante una llamada a WPUQueueApc, que se usó para iniciar la operación superpuesta. Se puede llamar a esta función desde cualquier contexto de proceso y subproceso, incluso un contexto diferente del subproceso y el proceso que se usó para iniciar la operación superpuesta.

WPUQueueApc toma como parámetros de entrada un puntero a una estructura WSATHREADID (proporcionada al proveedor a través del parámetro de entrada lpThreadId ), un puntero a una función de APC que se va a invocar y un valor de contexto que se pasa posteriormente a la función de APC. Dado que solo hay disponible un único valor de contexto, la propia función de APC no puede ser la rutina de finalización especificada por el cliente. En su lugar, el proveedor de servicios debe proporcionar un puntero a su propia función de APC que usa el valor de contexto proporcionado para tener acceso a la información de resultado necesaria para la operación superpuesta y, a continuación, invoca la rutina de finalización especificada por el cliente.

El prototipo de la rutina de finalización proporcionada por el cliente es el siguiente.

void CALLBACK 
CompletionRoutine(  
  IN DWORD           dwError, 
  IN DWORD           cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD           dwFlags 
);

El parámetro CompletionRoutine es un marcador de posición para un nombre de función proporcionado por el cliente. dwError especifica el estado de finalización de la operación superpuesta, como se indica en lpOverlapped. El parámetro cbTransferred especifica el número de bytes recibidos. dwFlags contiene información que habría aparecido en lpFlags si la operación de recepción se hubiera completado inmediatamente. Esta función no devuelve ningún valor.

Se puede llamar a las rutinas de finalización en cualquier orden, pero no necesariamente el mismo orden en el que se completan las operaciones superpuestas. Sin embargo, se garantiza que los búferes publicados se rellenen en el mismo orden en el que se suministran.

Nota

Todas las E/S iniciadas por un subproceso determinado se cancelan cuando se cierra ese subproceso. En el caso de los sockets superpuestos, las operaciones asincrónicas pendientes pueden producir un error si el subproceso está cerrado antes de que se completen las operaciones. Consulte ExitThread para obtener más información.

Requisitos

Requisito Value
Cliente mínimo compatible compilación 20348 de Windows 10
Servidor mínimo compatible compilación 20348 de Windows 10
Encabezado ws2spi.h

Consulte también

WPUCloseEvent

WPUCreateEvent

WPUQueueApc

LPWSPGetOverlappedResult

LPWSPSocket