1

我在 IOCP 结构化服务器上​​使用 wsasend。有一个问题。

wsabuf [bufcount - 1] .buf = pPacket-> GetPacketBufferPtr ();
wsabuf [bufcount - 1] .len = (int) pPacket-> Get_PacketSize ();
iSendSize + = wsabuf [bufcount - 1] .len;
bufcount ++;
int retval = WSASend (pSession-> socket, wsabuf, bufcount-1, & sendbytes,flag, & pSession-> overlapped_Send, NULL);
if (retval == SOCKET_ERROR)
{

    if (WSAGetLastError ()! = WSA_IO_PENDING)
    {
      ......
    }
}
if (retval == 0)
{
    if (sendbytes! = iSendSize)
    {
       ........
    }
}
.....

在上面的代码中,我保存了要发送到 wsabuf 的数据包,并通过 wsasend 发送它。最后,我比较了 sendbytes 和 iSendSize 。顺便说一句,sendbytes 和 iSendSize 是不同的。我不知道为什么。

4

1 回答 1

1

驱动程序返回的实际传输字节数,仅当操作完成时。io 子系统复制此值以IO_STATUS_BLOCK.Information传输给 io 操作。结果用户取回了这个值。但当然只有在操作完成后。

win32 api 使用OVERLAPPED到位IO_STATUS_BLOCK- 重新解释强制OVERLAPPED转换IO_STATUS_BLOCK并将此指针传递给内核。所以InternalHigh将包含实际传输的字节数,但只有在操作完成之后(如果错误同步返回 - io 子系统不填充此字段,因此它在错误时值为 undefined。当然是 0)。

WSASend获取值(在调用内核之后)OVERLAPPED.InternalHigh,如果lpNumberOfBytesSent不是 0 - 将其复制到此处。如果您使用同步套接字句柄 - 此时 io 操作已经完成(io 子系统内部等待此,然后返回给调用者)并且有效值OVERLAPPED.InternalHigh将被复制到*lpNumberOfBytesSent

在代码中,这看起来像

if (!lpOverlapped)
{
    OVERLAPPED Overlapped = {};
    lpOverlapped = &Overlapped;
}

ZwDeviceIoControlFile(.. reinterpret_cast<IO_STATUS_BLOCK*>(lpOverlapped) ..)

if (lpNumberOfBytesSent)
{
  *lpNumberOfBytesSent = (ULONG)lpOverlapped->InternalHigh;
}

在异步套接字句柄的情况下,从内核返回后操作通常尚未完成。结果lpOverlapped->InternalHigh尚未填充正确的字节数。和

*lpNumberOfBytesSent = (ULONG)lpOverlapped->InternalHigh;

结果不正确(未定义,如果您和系统未对其进行初始化,则说为 0)。

结论 - 你不能sendbytes用于异步 io 操作。这里是未定义的。当 io 完成时,你可以并且需要得到这个值。你如何得到它已经取决于你如何通知完成。

  • 如果你使用BindIoCompletionCallback - 你 FileIOCompletionRoutinedwNumberOfBytesTransfered 争论中得到它
  • 如果你使用CreateThreadpoolIo- 你 IoCompletionCallbackNumberOfBytesTransferred争论中得到它
  • 如果您使用自己的IOCP并且 GetQueuedCompletionStatus- 在操作完成后,您将返回指向您lpOverlapped使用的 in 调用WSASend(或其他 io 函数 - 这已经是您的任务确定在哪里lpOverlapped使用)。此时您可以调用GetOverlappedResultlpOverlappedbWait您可以设置为任何值 - 没关系,因为操作已经完成 - api 在任何情况下都会立即返回而无需等待)并且您在lpNumberOfBytesTransferred. 但是 只需将 值GetOverlappedResult复制到,以便您可以直接使用,无需调用lpOverlapped->InternalHigh*lpNumberOfBytesTransferredInternalHighGetOverlappedResult
于 2017-12-20T15:17:32.630 回答