2015-02-05 64 views
3

我遇到了獲取winsock RIO工作的問題。 似乎每次我發佈RIOReceive時,它都會立即返回0字節傳輸,並且我的對等方無法收到消息。Winsock RIO:RIOReceive立即返回沒有bytesTransferred

在發佈RIOReceive之後,我等待RIODequeCompletion,它立即使用numResults = 1來實現deques,但是當我檢查RIORESULT結構的bytesTransferred時,結果爲0.這告訴我,我沒有正確設置這個東西,但是我找不到能夠告訴我還有什麼我應該做的文檔或例子。

互聯網似乎對RIO很少。我瀏覽了MSDN,Len Holgate with TheServerFramework,這個網站和兩個GitHub RIO服務器。

RIOEchoServer和RIOServer_sm9是在GitHub上,但我不能發佈兩個以上的鏈路(這是我的第一個問題,關於這個網站)。

此代碼僅用於證明事物。它目前不能設置爲使用sendCQ,不處理錯誤好,等...

這裏的準備工作:

void serverRequestThread() { 

//init buffers 

//register big buffers 
recvBufferMain = rio.RIORegisterBuffer(pRecvBufferMain, bufferSize); 
sendBufferMain = rio.RIORegisterBuffer(pSendBufferMain, bufferSize); 

if (recvBufferMain == RIO_INVALID_BUFFERID) { 
    cout << "RIO_INVALID_BUFFERID" << endl; 
} 

if (sendBufferMain == RIO_INVALID_BUFFERID) { 
    cout << "RIO_INVALID_BUFFERID" << endl; 
} 

//create recv buffer slice 
recvBuffer1.BufferId = recvBufferMain; 
recvBuffer1.Offset = 0; 
recvBuffer1.Length = 10000; 

//create send buffer slice 
sendBuffer1.BufferId = sendBufferMain; 
sendBuffer1.Offset = 0; 
sendBuffer1.Length = 10000; 

//completion queue 
recvCQ = rio.RIOCreateCompletionQueue(CQsize, NULL); 
sendCQ = rio.RIOCreateCompletionQueue(CQsize, NULL); 

if (recvCQ == RIO_INVALID_CQ) { 
    cout << "RIO_INVALID_CQ" << endl; 
} 

if (sendCQ == RIO_INVALID_CQ) { 
    cout << "RIO_INVALID_CQ" << endl; 
} 

//start a loop for newly accept'd socket 
while (recvCQ != RIO_INVALID_CQ && sendCQ != RIO_INVALID_CQ) { 

    //get accept'd socket 
    struct sockaddr_in saClient; 
    int iClientSize = sizeof(saClient); 
    acceptSocket = accept(listenSocket, (SOCKADDR*)&saClient, &iClientSize); 

    if (acceptSocket == INVALID_SOCKET) { 
     cout << "Invalid socket" << endl; 
     printError(); 
    } 

    //register request queue 
    requestQueue = rio.RIOCreateRequestQueue(
     acceptSocket,  //socket 
     10,     //max RECVs on queue 
     1,     //max recv buffers, set to 1 
     10,     //max outstanding sends 
     1,     //max send buffers, set to 1 
     recvCQ,    //recv queue 
     recvCQ,    //send queue 
     pOperationContext //socket context 
     ); 

    if (requestQueue == RIO_INVALID_RQ) { 
     cout << "RIO_INVALID_RQ" << endl; 
     printError(); 
    } 

我現在發佈RIOReceive:

//start a loop to repin recv buffer for socket 
    while (acceptSocket != INVALID_SOCKET) { 

     //pin a recv buffer to wait on data 
     recvSuccess = rio.RIOReceive(
      requestQueue,   //socketQueue 
      &recvBuffer1,   //buffer slice 
      1,      //set to 1 
      RIO_MSG_WAITALL,      //flags 
      0);      //requestContext 

     if (recvSuccess == false) { 
      cout << "RECV ERROR!!!!!!!!\n"; 
      printError(); 
     } 

     //wait for recv to post in queue 

     //std::this_thread::sleep_for(std::chrono::milliseconds(3000)); 

由於當我打電話RIODequeCompletion,它返回1:

 numResults = 0; 
     while (numResults == 0) numResults = rio.RIODequeueCompletion(recvCQ, recvArray, 10); 

     if (numResults == RIO_CORRUPT_CQ) { 

      cout << "RIO_CORRUPT_CQ" << endl; 

     } else if (numResults == 0) { 

      cout << "no messages on queue\n"; 

     } else if (numResults > 0) { 

,但是當我檢查RIORESULT的bytesTransferred,它「總是0:

  if (recvArray[0].BytesTransferred > 0) { 

       //process results 
       if (pRecvBufferMain[0] == 'G') { 

        //set respnose html 
        strcpy(pSendBufferMain, responseHTTP); 

        sendSuccess = rio.RIOSend(
         requestQueue, //socketQueue 
         &sendBuffer1, //buffer slice 
         1,    //set to 1 
         0,    //flags 
         0);    //requestContext 

       } else if (pRecvBufferMain[0] == 'P') { 

        //process post 


       } else { 
        //recv'd a bad message 

       } 

      } //end bytesTransferred if statement 

      //reset everything and post another recv 

     }//end response if statement 

     std::this_thread::sleep_for(std::chrono::milliseconds(100)); 

    }//end while loop for recv'ing 

    std::this_thread::sleep_for(std::chrono::milliseconds(100)); 

}//end while loop for accept'ing 

}// end function 

就像我說的,我可能沒有使用正確RIOReceive,和/或我沒有設置,我需要(沒有現在)正確的套接字選項。

我明白任何幫助。

+0

爲什麼您首先使用RIO而不是傳統的套接字I/O,或重疊I/O或I/O完成端口?爲什麼輪詢RIO隊列而不是在事情準備好時得到通知?你在'RIOCreateRequestQueue()'中對發送隊列和接收隊列都使用'recvCQ',你並沒有使用'sendCQ'作爲發送隊列。 – 2015-02-05 20:41:28

+0

我只是在研究RIO,看看它是否適合我的服務器。如您所知,輪詢效率不高,但在負載較重的情況下,輪詢會提供最高的性能,因爲IOCP會吃掉週期。這也是最簡單的,所以這就是爲什麼我在這裏使用它,只是爲了獲得一些數字。雅,sendCQ沒有掛鉤。我暫時刪除它進行調試,但它會回來。謝謝你問...你有什麼想法,爲什麼我沒有得到RIOReceive/RIODequeueCompletion/RIORESULT字節? – Michael220 2015-02-05 20:54:22

+0

我從來沒有使用過RIO。 IOCP一直是首選的高性能解決方案。我不知道爲什麼MS覺得有必要引入另一個套接字API時,他們已經有幾個。在任何情況下,接收到的0字節的結果通常表示套接字已被對等關閉。 – 2015-02-05 21:03:58

回答

0

嘗試刪除RIO_MSG_WAITALL。可能有一個錯誤,你只能得到關閉通知(字節== 0),而不是完成其中的數據。無論哪種方式,看看代碼是否在沒有標誌的情況下工作會很有趣。

我的示例服務器和測試是否在您的硬件上工作?

+0

謝謝Len。這是貢獻的一件事。在我刪除之後,我還發現我沒有正確確定我的CQ的大小,使其足以滿足我所有的RQ。我確實讀過了所有的博客,他們一直很有幫助,但我還沒有真正運行代碼。我一直專注於TCP,我認爲我可以學習理論並構建一個簡單的服務器。現實情況已經不同了,所以我可以回去運行你的UDP服務器/客戶端並從那裏增加。感謝您分享您的工作! – Michael220 2015-02-10 02:39:31

+0

我詢問有關我的硬件測試的原因是我有一些客戶在各種機器上安裝了奇怪的東西,並且顯然影響了RIO。所以最好先獲得一個已知可以工作的基準示例。很高興你發現了這個問題。如果你發佈更多的請求(並且他們完成),那麼CQ的問題就會被破壞,而不是CQ中的空間;所以你需要小心。 – 2015-02-10 09:16:52

0

我在使用RioReceive和RioNotify以及RioDequeueCompletion進行排隊的完成結果中遇到類似的零字節接收問題。我還會在出隊完成結果中看到WSA​​EINVAL的「狀態」值(無效參數= 10022),這似乎表明接收呼叫的WSA錯誤代碼。

的具體原因,我有錯誤是因爲我已經爲一個receiveBuffer分配的內存,我試圖通過該緩衝區指針中給出的RIO_BUFFER_SEGMENT我的緩衝區手柄RioReceive強似的IntPtr的返回由RioRegisterBuffer

我完全怪自己使用過多的非類型化IntPtrs,失去類型檢查。 :)