2017-02-23 53 views
1

假設我有兩個程序,一個客戶端和一個服務器,並且我在同一臺計算機上運行客戶端和服務器(所以速度非常快),並且說客戶端套接字的接收緩衝區是空的,並且服務器不會向客戶端發送任何數據,除非客戶端告訴服務器這樣做。在這種情況下,WSASend()和WSARecv()的完成數據包的順序是什麼?

現在,在客戶端,我打電話WSASend()然後之後我打電話WSARecv()

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

所以在上面的代碼中,WSASend()告訴服務器發送一些數據到客戶端(比如:字符串"hello")。

現在經過一段時間後,兩個完成的數據包將被放置在完成端口:

  • 第一個完成數據包是WSASend()(告訴我,數據 已被放置在客戶端套接字的發送緩衝區)。

  • 第二完成數據包是用於WSARecv()(告訴我,數據 已放置在我傳遞給WSARecv()當我 把它稱爲緩衝液)。

現在我的問題是:有沒有可能爲WSARecv()完成數據包被放置在完成端口的完成數據包之前WSASend()(所以當我打電話GetQueuedCompletionStatus()我將獲得WSARecv()先完成數據包)?

+0

是的,這可能(但可能性極低) - 但是對於你將這個數據包放入iocp的命令有什麼不同?你不能依賴這個 – RbMm

回答

2

你絕不能假設你得到的任何完成包的順序。你必須獨立於這一知識 - 這是完整的操作。

您必須定義一些繼承自OVERLAPPED的結構,並且此結構會放置與操作相關的所有數據。包括描述操作類型的標籤。所以,當你從IOCP提取指針OVERLAPPED你將它轉換爲這種結構,將知道 - 這是爲recvsend,連接或斷開。例如

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); 
    ... 
} 
相關問題