wsasend lpnumberofbytesSent

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wsasend lpnumberofbytesSent相关的知识,希望对你有一定的参考价值。

我在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是不同的。我不知道为什么。

答案

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

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

WSASendOVERLAPPED.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完成时得到这个值。你如何得到它已经取决于你如何通知完成。

  • 如果你使用BindIoCompletionCallback - 你在FileIOCompletionRoutinedwNumberOfBytesTransfered论证中得到它
  • 如果你使用CreateThreadpoolIo-你在IoCompletionCallbackNumberOfBytesTransferred论证中得到它
  • 如果你使用自己的IOCP和GetQueuedCompletionStatus - 你得到了指向你的lpOverlapped的指针,用于调用WSASend(或其他一些io函数 - 这已经是你的任务决定了这个lpOverlapped使用的地方)在操作完成后。在这一点上你可以调用GetOverlappedResult这个lpOverlappedbWait你可以设置为任何值 - 无关紧要因为操作已经完成 - api将在任何情况下立即返回而无需等待)并且你在lpNumberOfBytesTransferred中获得了实际的传输字节数。然而GetOverlappedResult只是将lpOverlapped->InternalHigh值复制到*lpNumberOfBytesTransferred所以你可以直接,自己使用InternalHigh而不打电话给GetOverlappedResult

以上是关于wsasend lpnumberofbytesSent的主要内容,如果未能解决你的问题,请参考以下文章

如何确保 WSASend() 将发送数据?

TCP WSASend 完成标准

具有多个缓冲区的 WSASend() - 可以完成不完整吗?

GQCS 收到通知,当 WSAsend 返回 0 时?

连续性多个 WSASend() io 完成端口

在迂回的 WSASend 中阻塞数据包