2015-02-05 131 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,失去类型检查。 :)