LPWSPRECVFROM 回调函数 (ws2spi.h)

LPWSPRecvFrom 函数接收数据报并存储源地址。

语法

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
)
{...}

参数

[in] s

标识套接字的描述符。

[in, out] lpBuffers

指向 WSABUF 结构数组的指针。 每个 WSABUF 结构都包含指向缓冲区的指针和缓冲区的长度(以字节为单位)。

[in] dwBufferCount

lpBuffers 数组中的 WSABUF 结构数。

[out] lpNumberOfBytesRecvd

指向此调用接收的字节数的指针。

[in, out] lpFlags

指向标志的指针。

[out] lpFrom

指向 sockaddr 结构中的缓冲区的可选指针,该缓冲区将在重叠操作完成后保留源地址。

[in, out] lpFromlen

指向 lpFrom 缓冲区大小的指针(以字节为单位),仅当指定 lpFrom 时才需要。

[in] lpOverlapped

对于) , (忽略指向 WSAOverlapped 结构的指针。

[in] lpCompletionRoutine

类型:_In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

指向完成接收操作时调用的完成例程的指针, (忽略非重叠套接字) 。

\\[in\\] lpThreadId

指向提供程序在后续调用 WPUQueueApc 时要使用的 WSATHREADID 结构的指针。 在 WPUQueueApc 函数返回之前,提供程序应存储引用的 WSATHREADID 结构 (而不是指向同一) 的指针。

[in, out] lpErrno

指向错误代码的指针。

返回值

如果未发生任何错误,并且接收操作已立即完成, 则 LPWSPRecvFrom 返回零。 请注意,在这种情况下,完成例程(如果指定)已排队。 否则,将返回值 SOCKET_ERROR,并且 lpErrno 中提供了特定的错误代码。 错误代码WSA_IO_PENDING指示重叠操作已成功启动,稍后将指示完成。 任何其他错误代码指示未启动重叠操作,也不会发生完成指示。

错误代码 含义
WSAENETDOWN
网络子系统发生故障。
WSAEFAULT
lpFromlen 参数无效:lpFrom 缓冲区太小,无法容纳对等地址,或者 lpbuffer 未完全包含在用户地址空间的有效部分中。
WSAEINTR
(阻止) 调用已通过 LPWSPCancelBlockingCall 取消。
WSAEINPROGRESS
正在阻止 Windows 套接字调用,或者服务提供商仍在处理回调函数。
WSAEINVAL
例如,套接字尚未绑定 (LPWSPBind) ,或者未使用重叠标志创建套接字。
WSAEISCONN
套接字已连接。 无论套接字是面向连接的还是无连接的,都不允许使用此函数。
WSAENETRESET
由于操作执行过程中持续的活动检测到故障,连接损坏。
WSAENOTSOCK
:描述符不是套接字。
WSAEOPNOTSUPP
MSG_OOB已指定,但套接字不是流样式(如类型SOCK_STREAM),与此套接字关联的通信域中不支持 OOB 数据,或者套接字是单向的,仅支持发送操作。
WSAESHUTDOWN
套接字已关闭;在调用了 LPWSPShutdown 并将其设置为 SD_RECEIVE 或 SD_BOTH 后,无法在套接字上运行 LPWSPRecvFrom
WSAEWOULDBLOCK
**Windows NT:**
重叠套接字:存在过多未完成的重叠 I/O 请求。未重叠的套接字:套接字标记为非阻止,并且无法立即完成接收操作。
WSAEMSGSIZE
消息太大,无法放入指定的缓冲区,对于不可靠的协议, (仅) 不适合缓冲区的消息的任何尾随部分被丢弃。
WSAECONNRESET
执行硬性或异常关闭的远程端重置了虚拟线路。 因为套接字不可再用,应用程序应关闭套接字。 在 UDP 数据报套接字上,此错误将指示以前的发送操作导致 ICMP“端口无法访问”消息。
WSAEDISCON
套接字面向消息,虚拟线路由远程端正常关闭。
WSA_IO_PENDING
已成功启动重叠操作,稍后将指示完成。
WSA_OPERATION_ABORTED
由于套接字关闭,重叠操作已取消。

注解

LPWSPRecvFrom 函数主要用于由 指定的无连接套接字。 套接字的本地地址必须已知。 这可以通过 LPWSPBind 显式完成,也可以通过 LPWSPSendToLPWSPJoinLeaf 隐式完成。

对于重叠套接字,此函数用于发布一个或多个缓冲区,当传入数据在可能连接的) 套接字 (上可用时,传入数据将放入其中,之后客户端指定的完成指示 (调用完成例程或事件对象的设置) 发生。 如果操作未立即完成,则通过完成例程或 LPWSPGetOverlappedResult 检索最终完成状态。 另请注意,在指示完成之前, lpFromlpFromlen 指向的值不会更新。 在更新这些值之前,应用程序不得使用这些值或干扰这些值,因此客户端不得对这些参数使用自动 (即基于堆栈的) 变量。

如果 lpOverlappedlpCompletionRoutine 均为 null,则此函数中的套接字将被视为非重叠套接字。

对于未重叠的套接字, 将忽略 lpOverlappedlpCompletionRoutinelpThreadId 参数。 传输已接收和缓冲的任何数据都将复制到提供的用户缓冲区中。 对于传输当前未接收和缓冲数据的阻塞套接字,调用将阻止,直到根据 LPWSPRecv 分配的阻塞语义接收数据为止。

提供的缓冲区按它们在 lpBuffers 指向的数组中的出现顺序进行填充,并且会打包缓冲区,以便不创建任何孔。

lpBuffers 参数指向的 WSABUF 结构的数组是暂时性的。 如果此操作以重叠方式完成,则服务提供商负责在从此调用返回之前捕获指向 WSABUF 结构的此指针数组。 这使 Windows 套接字 SPI 客户端能够生成基于堆栈的 WSABUF 数组。

对于无连接套接字类型,数据源自的地址将复制到 lpFrom 指向的缓冲区。 在输入时, lpFromlen 指向的值初始化为此缓冲区的大小,并在完成时进行修改,以指示存储在那里的地址的实际大小。

如前面所述,对于重叠套接字, lpFromlpFromlen 参数在重叠 I/O 完成之前不会更新。 因此,这些参数指向的内存必须对服务提供商保持可用,并且不能在 Windows 套接字 SPI 客户端的堆栈帧上分配。 对于面向连接的套接字,将忽略 lpFromlpFromlen 参数。

例如,对于字节流样式套接字 (类型SOCK_STREAM) ,传入数据将放入缓冲区,直到填充缓冲区、关闭连接或内部缓冲的数据耗尽。 无论传入数据是否填充所有缓冲区,重叠套接字都会显示完成指示。

对于面向消息的套接字,单个传入消息将放置在提供的缓冲区中,最大大小为提供的缓冲区的总大小,并且重叠的套接字会出现完成指示。 如果消息大于提供的缓冲区,则缓冲区将填充消息的第一部分。 如果服务提供程序支持MSG_PARTIAL功能,则会在套接字的 lpFlags 中设置MSG_PARTIAL标志,后续接收操作 () 将检索消息的其余部分。 如果不支持MSG_PARTIAL但协议可靠, 则 LPWSPRecvFrom 将生成错误 WSAEMSGSIZE ,并且可以使用具有较大缓冲区的后续接收操作来检索整个消息。 否则, (即协议不可靠且不支持MSG_PARTIAL) ,多余的数据将丢失, LPWSPRecvFrom 将生成错误 WSAEMSGSIZE。

lpFlags 参数可用于影响函数调用的行为,超出为关联套接字指定的选项。 也就是说,此函数的语义由套接字选项和 lpFlags 参数确定。 后者是使用以下任何值的按位 OR 运算符构造的。

含义
MSG_PEEK 速览传入数据。 数据会复制到缓冲区中,但不会从输入队列中删除。 此标志仅对未重叠的套接字有效。
MSG_OOB 处理带外 (OOB) 数据。
MSG_PARTIAL 此标志仅适用于面向消息的套接字。 在输出时,指示提供的数据是发送方传输的消息的一部分。 消息的剩余部分将在后续接收操作中提供。 清除了MSG_PARTIAL标志的后续接收操作指示发件人的消息结束。 作为输入参数,MSG_PARTIAL指示接收操作应完成,即使服务提供商只接收了消息的一部分。

 

 

对于面向消息的套接字,如果收到部分消息,则会在 lpFlags 参数中设置MSG_PARTIAL位。 如果收到完整的消息,MSG_PARTIAL会在 lpFlags 中清除。 在延迟完成的情况下, lpFlags 指向的值不会更新。 指示完成时,Windows 套接字 SPI 客户端应调用 LPWSPGetOverlappedResult 并检查 lpdwFlags 参数指向的标志。

如果重叠操作立即完成, LPWSPRecv 返回值零, lpNumberOfBytesRecvd 参数将更新为接收的字节数, lpFlags 参数指向的标志位也会更新。 如果重叠操作已成功启动并稍后完成, 则 LPWSPRecv 将返回SOCKET_ERROR并指示 错误代码WSA_IO_PENDING。 在这种情况下, lpNumberOfBytesRecvdlpFlags 不会更新。 当重叠操作完成时,通过完成例程 (中的 cbTransferred 参数(如果) 指定)或通过 LPWSPGetOverlappedResult 中的 l) 的 l) Transfer 参数指示传输的数据量。 标志值是通过检查 LPWSPGetOverlappedResultlpdwFlags 参数获取的。

提供程序必须允许从以前的 LPWSPRecv、LPWSPRecvFromLPWSPSend 或 LPWSPSendTo 函数的完成例程中调用此函数。 但是,对于给定的套接字,无法嵌套 I/O 完成例程。 这允许时间敏感型数据传输完全在抢占式上下文中进行。

lpOverlapped 参数在重叠操作期间必须有效。 如果多个 I/O 操作同时未完成,则每个操作都必须引用单独的重叠结构。 WSAOverlapped 结构在其自己的引用页中定义。

如果 lpCompletionRoutine 参数为 null,则当重叠操作完成时,如果包含有效的事件对象句柄,则服务提供程序会向 lpOverlappedhEvent 成员发出信号。 Windows 套接字 SPI 客户端可以使用 LPWSPGetOverlappedResult 等待或轮询事件对象。

如果 lpCompletionRoutine 不为 null,则 忽略 hEvent 成员,Windows 套接字 SPI 客户端可以使用该成员将上下文信息传递给完成例程。 当重叠操作完成时,服务提供商负责安排客户端指定的完成例程的调用。 由于必须在启动重叠操作的同一线程的上下文中执行完成例程,因此无法直接从服务提供程序调用它。 Ws2_32.dll 提供异步过程调用 (APC) 机制,以方便调用完成例程。

服务提供商通过调用 WPUQueueApc 安排在适当的线程和进程上下文中执行的函数。 可以从任何进程和线程上下文调用此函数,甚至是不同于用于启动重叠操作的线程和进程的上下文。

WPUQueueApc 将指向 WSATHREADID 结构的指针作为输入参数, (通过 lpThreadId 输入参数) 提供给提供程序、指向要调用的 APC 函数的指针以及随后传递给 APC 函数的上下文值。 由于只有单个上下文值可用,因此 APC 函数本身不能是客户端指定的完成例程。 服务提供商必须改为提供指向其自己的 APC 函数的指针,该函数使用提供的上下文值访问重叠操作所需的结果信息,然后调用客户端指定的完成例程。

客户端提供的完成例程的原型如下所示:

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

CompletionRoutine 是客户端提供的函数名称的占位符。 dwError 指定重叠操作的完成状态,如 lpOverlapped 所示。 cbTransferred 指定接收的字节数。 dwFlags 包含如果接收操作已立即完成,则会显示在 lpFlags 中的信息。 此函数不返回值。

可以按任何顺序调用完成例程,但不一定按照重叠操作完成的顺序调用。 但是,已过帐缓冲区的填充顺序与提供的顺序相同。

注意

当给定线程退出时,将取消由给定线程启动的所有 I/O。 对于重叠套接字,如果在操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息 ,请参阅 ExitThread

要求

   
最低受支持的客户端 Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器 Windows 2000 Server [仅限桌面应用]
标头 ws2spi.h

另请参阅

WPUQueueApc

LPWSPGetOverlappedResult

LPWSPSocket