【问题标题】:What is the order of the completion packets for WSASend() and WSARecv() in this case?在这种情况下,WSASend() 和 WSARecv() 的完成数据包的顺序是什么?
【发布时间】:2017-07-14 06:09:03
【问题描述】:

假设我有两个程序,一个客户端和一个服务器,并且我在同一台计算机上运行客户端和服务器(所以速度非常快),并且说客户端套接字的接收缓冲区是空的,并且服务器不会向客户端发送任何数据,除非客户端告诉服务器这样做。

现在在客户端,我调用WSASend(),然后调用WSARecv()

WSASend(...);    // tell the server to send me some data
WSARecv(...);

所以在上面的代码中,WSASend() 是告诉服务器向客户端发送一些数据(例如:字符串"hello")。

现在一段时间后,完成端口会放置两个完成包:

  • 第一个完成包是给WSASend()的(告诉我数据 已被放置在客户端套接字的发送缓冲区中)。

  • 第二个完成包是给WSARecv()的(告诉我数据 已放置在我传递给WSARecv() 时的缓冲区中 叫它)。

现在我的问题是:WSARecv() 的完成数据包是否可以在 WSASend() 的完成数据包之前放置在完成端口中(所以当我调用 GetQueuedCompletionStatus() 时,我会得到 @987654332 的完成数据包@先)?

【问题讨论】:

  • 是的,这有可能(但可能性很小)-但是对于您来说,这个数据包将被放置到 iocp 的顺序有什么不同?你不能依赖这个

标签: c sockets winapi winsock iocp


【解决方案1】:

您绝不能假设您收到的任何完成数据包的顺序。你必须有独立于这方面的知识——这是操作完成的。

你必须定义一些继承自OVERLAPPED的结构,这个结构放置所有与操作相关的数据。包括描述操作类型的标签。因此,当您从 IOCP 中提取指向 OVERLAPPED 的指针时,您会将其转换为该结构并且会知道 - 这是用于 recv 还是 send,连接或断开连接.. 例如

class IO_IRP : public OVERLAPPED 
{
  //...
  DWORD m_opCode;// `recv`, `send`, `dsct`, `cnct`

  IO_IRP(DWORD opCode,...) : m_opCode(opCode) {}

    VOID IOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered)
    {
        // switch (m_opCode)
        m_pObj->IOCompletionRoutine(m_packet, m_opCode, dwErrorCode, dwNumberOfBytesTransfered, Pointer);
        delete this;
    }

    static VOID CALLBACK _IOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
    {
        static_cast<IO_IRP*>(lpOverlapped)->IOCompletionRoutine(dwErrorCode, dwNumberOfBytesTransfered);
    }

};

// recv
if (IO_IRP* Irp = new IO_IRP('recv', ..))
{
  WSARecv(..., Irp);
  ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多