Winsock RIO: RIOReceive возвращается немедленно без передачи байтов

У меня проблемы с работой Winsock RIO. Кажется, что каждый раз, когда я отправляю сообщение RIOR, он сразу же возвращает 0 передаваемых байтов, и мой коллега не может получить сообщение.

После публикации RIOReceive я жду RIODequeCompletion, который немедленно запрашивает с numResults = 1, но когда я проверяю bytesTransferred структуры RIORESULT, это 0. Это говорит мне, что я не настраиваю эту вещь должным образом, но я могу не найти документы или примеры, которые говорят мне, что еще я должен делать.

В интернете, похоже, очень мало информации о РИО. Я просмотрел MSDN, Лена Холгейта с 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();
    }

Я теперь отправляю RIOR получить:

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

но когда я проверяю bytesTransferred RIORESULT, это всегда 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, и / или я не устанавливаю правильные опции сокетов, которые мне нужны (сейчас их нет).

Я ценю любую помощь с этим.

2 ответа

Решение

Попробуйте удалить RIO_MSG_WAITALL, Может быть ошибка, из-за которой вы получаете только уведомление о закрытии (байт == 0), а не завершение с данными в нем. В любом случае было бы интересно посмотреть, работает ли код без флага.

Мои примеры серверов и тесты работают на вашем оборудовании?

Я столкнулся с аналогичной проблемой отсутствия нулевых байтов в моем результате завершения с удалением из очереди при использовании RioReceive с RioNotify и RioDequeueCompletion. Я бы также увидел значение "Status" WSAEINVAL (Invalid Parameter = 10022) в моем результате завершения в режиме ожидания, это, кажется, указывает на код ошибки WSA для вызова Receive.

Конкретная причина, по которой у меня возникла ошибка, заключается в том, что я выделил память для receiveBuffer и пытался передать этот указатель буфера в качестве дескриптора буфера в RIO_BUFFER_SEGMENT, переданном RioReceive, вместо передачи IntPtr, возвращенного RioRegisterBuffer.

Я полностью виню себя за использование слишком большого количества нетипизированных IntPtrs и за потерю проверки типов.:)

Другие вопросы по тегам