2015-02-05 7 views
3

winsock RIO 작동에 문제가 있습니다. RIOReceive를 게시 할 때마다 즉시 0 바이트가 전송되고 내 피어가 메시지를 가져올 수없는 것으로 보입니다.Winsock RIO : RIOReceive는 bytesTransferred없이 즉시 반환합니다.

RIOReceive 게시 한 후 RIODequeCompletion 즉시 numResults 함께 deques = 1,하지만 내가 RIORESULT 구조체의 bytesTransferred 검사 할 때 0입니다.이 제대로 설정하지 않고 있음을 말해줍니다. ,하지만 내가해야할 일을 알려주는 문서 나 예제를 찾을 수는 없습니다.

인터넷에 RIO가 거의없는 것 같습니다. MSDN, Len Holgate with TheServerFramework,이 사이트 및 2 개의 GitHub RIO 서버를 살펴 보았습니다.

RIOEchoServer 및 RIOServer_sm9는 GitHub에 있지만 두 개 이상의 링크를 게시 할 수 없습니다 (이 사이트에서는 내 첫 번째 질문입니다).

이 코드는 입증 된 것입니다.

//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)); 

로 : 나는 지금 RIOReceive을 게시

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(); 
    } 

: 현재, 여기

은 준비 작업의 ... 등 잘 오류를 처리하지 않습니다 sendCQ를 사용하도록 설정 아니에요 내가 RIODequeCompletion를 호출하는 즉시, 그것은 하나가 반환

 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

기존 소켓 I/O 또는 겹친 I/O 또는 I/O 완료 포트 대신 RIO를 처음 사용하는 이유는 무엇입니까?왜 준비가되었는지 알리는 대신 RIO 대기열을 폴링하는 이유는 무엇입니까? 그리고'RIOCreateRequestQueue()'에서 send와 recv 대기열 모두에 대해'recvCQ'를 사용하고 있고, send 대기열에 대해'sendCQ'를 사용하고 있지 않습니다. –

+0

저는 RIO가 내 서버에 적합한 지 확인하려고합니다. 아시다시피 폴링은 효율적이지 않지만 부하가 많은 경우 IOCP가주기를 먹을 것이므로 가장 높은 성능을 제공합니다. 또한 가장 간단한 방법이기 때문에 여기에서 보드를 사용하여 보드에 숫자를 표시합니다. 예, sendCQ가 연결되지 않았습니다. 내가 디버깅을 위해 일시적으로 그것을 제거하지만, 다시 갈거야. 요청 주셔서 감사합니다 ... 왜 내가 RIOReceive/RIODequeueCompletion/RIORESULT의 바이트를 가져 오지 않을거야에 대한 아이디어가 있습니까? – Michael220

+0

전 RIO를 사용한 적이 없습니다. IOCP는 언제나 선호되는 고성능 솔루션이었습니다. MS가 왜 이미 여러 소켓 API를 가지고있을 때 또 다른 소켓 API를 소개해야 할 필요성을 느꼈는지 나는 모른다. 어쨌든 0 바이트의 결과는 대개 소켓이 피어에 의해 닫혔다는 것을 나타냅니다. –

답변

0

RIO_MSG_WAITALL을 삭제 해보세요. 거기에있는 데이터로 완료를받는 것보다 닫기 알림 (바이트 == 0) 만 가져 오는 버그가있을 수 있습니다. 어쨌든 코드가 플래그없이 작동하는지 확인하는 것은 흥미로울 것입니다.

예제 서버와 테스트가 하드웨어에서 작동합니까?

+0

감사합니다. Len. 이것이 기여한 것 중 하나였습니다. 내가 그것을 제거한 후에 나는 또한 나의 CQ가 모든 나의 RQ를 위해 충분히 커질 수 없음을 발견했다. 나는 당신의 모든 블로그를 통해 읽었으며, 그들은 매우 도움이되었지만, 실제로 코드를 아직 실행하지 못했습니다. 나는 TCP에 초점을 맞추어 왔고, 나는 이론을 배우고 간단한 서버를 만들 수있을 것이라고 생각했다. 현실은 다르다. 그래서 나는 돌아가서 UDP 서버/클라이언트를 실행하고 거기에서 증가 할 수있다. 작업을 공유해 주셔서 감사합니다! – Michael220

+0

내가 하드웨어에서 작동하는 테스트에 대해 묻는 이유는 여러 컴퓨터에 이상한 것들이 설치되어 있고 RIO에 영향을 미친 일부 클라이언트가 있다는 것입니다. 따라서 먼저 작동하는 것으로 알려진 기본 예제를 얻는 것이 좋습니다. 다행히 문제를 발견했습니다. CQ에 공간이있는 것보다 많은 요청을 게시하고 완료하면 CQ가 손상됩니다. 그래서 그것에 대해 조심해야합니다. –

0

RioNotify 및 RioDequeueCompletion과 함께 RioReceive를 사용하는 동안 대기열에서 완료 한 결과에서 0 바이트를 수신하는 것과 비슷한 문제가 발생했습니다. 또한 대기열에서 내린 완료 결과에서 WSAEINVAL (잘못된 매개 변수 = 10022)의 '상태'값이 표시됩니다.이 값은 수신 호출의 WSA 오류 코드를 나타내는 것으로 보입니다. 나는 receiveBuffer 메모리를 할당했고 내가 대신을 IntPtr가 RioRegisterBuffer에 의해 반환 을 전달하는 RioReceive에게 주어진 RIO_BUFFER_SEGMENT 내 버퍼 핸들로 포인터 버퍼 을 통과하려고했기 때문에

나는 오류가 발생한 특정 이유는.

너무 많은 타입이 지정되지 않은 IntPtrs를 사용하고 형식 검사를 잃어 버렸다는 것을 완전히 비난합니다. :)