Потоки и структура общения - PullRequest
0 голосов
/ 19 марта 2011

Я занимаюсь проектом, который требует от меня получать сообщения от многих отправителей. Мой сервер recv использует поток для непрерывного recv данных по протоколу UDP. У меня есть структура с именем struct BufferData в заголовочном файле для организации моего полученного буфера от клиента. Вот мой struct выглядит так:

struct BufferData
{
    char Buffer1[BYTES];
    char Buffer2[BYTES];
    char Buffer3[BYTES];
    char MixedBuffer1[BYTES];
    char MixedBuffer2[BYTES];
    char MixedBuffer3[BYTES];
};

А вот моя функция потока recv в файле .cpp.

hThread = (HANDLE)_beginthreadex(NULL, 0, &CUdpSocket::ServerRecvThread, pRecvData, 0, &threadID); // Thread caller

unsigned __stdcall CUdpSocket::ServerRecvThread(void *threadArg) 
{   
    //-----------------------------------------------
    // Initialize Winsock
    //-----------------------------------------------
    // Create a receiver socket to receive datagrams
    //-----------------------------------------------
    // Bind the socket to any address and the specified port.
    //-----------------------------------------------
    // Call the recvfrom function to receive datagrams
    // on the bound socket.

    start:
         recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
    goto start;

    //-----------------------------------------------
    // Close the socket when finished receiving datagrams
    //-----------------------------------------------
    // Clean up and exit.

    return 0;
}

Однако я не знаю, как передать значение, содержащееся в RecvBuf, в мою структуру BufferData, поскольку это поток, и я не могу использовать прямой путь. Пожалуйста, помогите.

Спасибо.

1 Ответ

5 голосов
/ 19 марта 2011

Когда вы вызываете _beginthreadex, вызывая

_beginthreadex(NULL, 0, &CUdpSocket::ServerRecvThread, pRecvData, 0, &threadID);

Четвертый параметр этой функции (pRecvData) передается как параметр void* в функцию CUdpSocket::ServerRecvThread.В более общем смысле, если вам нужно передать информацию в эту функцию, вы можете сделать это, передав ее в качестве окончательного параметра этой функции.

Если вы хотите иметь возможность принимать полученные данные и передавать их вBufferData объект, рассмотрите возможность передачи указателя на этот BufferData объект в качестве параметра в поток.Таким образом, внутри вашей принимающей функции вы можете сделать что-то вроде этого:

unsigned __stdcall CUdpSocket::ServerRecvThread(void *threadArg) 
{   
    /* ... setup ... */

        // Convert the argument to what it really is - a pointer to the buffer.
    BufferData* data = static_cast<BufferData*>(threadArg);

    start:
         recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
         /* ... code to convert the receive buffer data into a data object... */
    goto start;

    /* ... cleanup ... */
}

Конечно, это очень рискованно, потому что это означает, что, когда поток начинает получать данные, он будет перезаписывать содержимоебуфера с самыми последними данными.Следовательно, я бы предложил вместо этого поддерживать какую-то синхронизированную очередь, которая содержит список всех пакетов, которые вы получили до сих пор.Если вы сделали это, то ваш поток мог бы вместо этого взять указатель на эту синхронизированную очередь, создавать свои собственные объекты BufferData всякий раз, когда он получает данные, а затем копировать их в очередь.Затем остальная часть вашей программы может обрабатывать получаемые данные, блокируя их до тех пор, пока в очереди не появится некоторое количество данных, а затем считывая данные из этой очереди.

Кроме того, на совершенно не связанной ноте не используйтеgoto для создания цикла, который обрабатывает вызовы recvfrom.Вместо этого используйте while (true) цикл ... он более читабелен.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...