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

La función LPWSPRecvFrom recibe un datagrama y almacena la dirección de origen.

Sintaxis

LPWSPRECVFROM Lpwsprecvfrom;

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

Parámetros

[in] s

Descriptor que identifica un socket.

[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.

[out] lpFrom

Puntero opcional a un búfer en la estructura sockaddr que contendrá la dirección de origen tras la finalización de la operación superpuesta.

[in, out] lpFromlen

Puntero al tamaño del búfer lpFrom , en bytes, necesario solo si se especifica lpFrom .

[in] lpOverlapped

Puntero a una estructura WSAOverlapped (omitida para sockets no superpuestos).

[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 sockets no superpuestos).

\\[in\\] lpThreadId

Puntero a una estructura WSATHREADID que 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 después de que la función WPUQueueApc devuelva.

[in, 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, LPWSPRecvFrom devuelve cero. Tenga en cuenta que, en este caso, la rutina de finalización, si se ha especificado ya se ha 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.
WSAEFAULT
El parámetro lpFromlen no era válido: el búfer lpFrom era demasiado pequeño para acomodar la dirección del mismo nivel o lpbuffers no está totalmente incluido dentro de una parte válida del espacio de direcciones del usuario.
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.
WSAEINVAL
El socket no se ha enlazado (por ejemplo, con LPWSPBind) o el socket no se crea con la marca superpuesta.
WSAEISCONN
El socket está conectado. Esta función no se permite con un socket conectado, tanto si el socket está orientado a la conexión como sin conexión.
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.
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
Se ha apagado el socket; no es posible ejecutar LPWSPRecvFrom en un socket después de invocar LPWSPShutdown 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.
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 de datagrama UDP, este error indicaría que una operación de envío anterior dio lugar a un mensaje icMP "Puerto inaccesible".
WSAEDISCON
El socket s está orientado a mensajes y el circuito virtual se cerró correctamente en 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
Se ha cancelado la operación superpuesta debido al cierre del socket.

Observaciones

La función LPWSPRecvFrom se usa principalmente en un socket sin conexión especificado por s El socket no debe estar conectado. 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 LPWSPSendTo o LPWSPJoinLeaf.

En el caso de los sockets superpuestos, esta función se usa para publicar uno o varios búferes en los que se colocarán los datos entrantes a medida que estén disponibles en un socket (posiblemente conectado), después de lo cual se produce la indicación de finalización especificada por el cliente (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. Tenga en cuenta también que los valores a los que apunta lpFrom y lpFromlen no se actualizan hasta que se indique la finalización. Las aplicaciones no deben usar ni molestar estos valores hasta que se hayan actualizado, por lo que el cliente no debe usar variables automáticas (es decir, basadas en pila) para estos parámetros.

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 han 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 los datos se reciban según la semántica de bloqueo asignada para LPWSPRecv.

Los búferes proporcionados se rellenan en el orden en que aparecen en la matriz a la que apunta 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 desde esta llamada. Esto permite a los clientes SPI de Windows Sockets crear matrices WSABUF basadas en pila.

En el caso de los tipos de socket sin conexión, la dirección desde la que se originaron los datos se copia en el búfer apuntado por lpFrom. En la entrada, el valor al que apunta lpFromlen se inicializa en el tamaño de este búfer y se modifica al finalizar para indicar el tamaño real de la dirección almacenada allí.

Como se indicó anteriormente para los sockets superpuestos, los parámetros lpFrom y lpFromlen no se actualizan hasta que se haya completado la E/S superpuesta. La memoria a la que apuntan estos parámetros debe permanecer disponible para el proveedor de servicios y no se puede asignar en el marco de pila del cliente SPI de Windows Sockets. Los parámetros lpFrom y lpFromlen se omiten para los sockets orientados a la conexión.

En el caso de los sockets de estilo de secuencia de bytes (por ejemplo, escriba 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 internamente en búfer. 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, se coloca un único 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 para el socket y las operaciones de recepción posteriores recuperarán el resto del mensaje. Si no se admite MSG_PARTIAL pero el protocolo es confiable, LPWSPRecvFrom 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 LPWSPRecvFrom genera el error WSAEMSGSIZE.

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.

Value Significado
MSG_PEEK Observa 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.

 

 

En el caso de los sockets orientados a mensajes, el bit de MSG_PARTIAL se establece en el parámetro lpFlags si se recibe un mensaje parcial. Si se recibe un mensaje completo, MSG_PARTIAL se borra en lpFlags. En el caso de la finalización retrasada, el valor al que apunta lpFlags no se actualiza. Cuando se haya indicado que el cliente SPI de Windows Sockets debe llamar a LPWSPGetOverlappedResult y examinar las marcas a las que apunta el parámetro lpdwFlags .

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 se completa la operación superpuesta, 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 examinando el parámetro lpdwFlags de LPWSPGetOverlappedResult.

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. Un 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. 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 una función que se va a ejecutar en el subproceso y el contexto de proceso adecuados mediante una llamada a WPUQueueApc. 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 
);

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. 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, aunque no necesariamente en el mismo orden en que se completan las operaciones superpuestas. Sin embargo, se garantiza que los búferes publicados se rellenen en el mismo orden en 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

   
Cliente mínimo compatible Windows 2000 Professional [solo aplicaciones de escritorio]
Servidor mínimo compatible Windows 2000 Server [solo aplicaciones de escritorio]
Encabezado ws2spi.h

Consulte también

WPUQueueApc

LPWSPGetOverlappedResult

LPWSPSocket