2016-12-30 4 views
0

Как читать QLocalSocket/QDataStream?Как читать QLocalSocket/QDataStream, чтобы избежать взаимоблокировок?

У меня есть программа, которая связывается с другим через именованные каналы, используя QLocalSocket и QDataStream. Слот recieveMessage() подключен к сигналу QLocalSocketreadyRead().

void MySceneClient::receiveMessage() 
{  
    qint32 msglength; 
    (*m_stream) >> msglength; 

    char* msgdata = new char[msglength]; 
    int read = 0; 
    while (read < msglength) { 
     read += m_stream->readRawData(&msgdata[read], msglength - read); 
    } 
    ... 
} 

Я считаю, что применение иногда висит на readRawData(). То есть, он успешно читает 4 байтовый заголовок, но никогда не возвращается с readRawData().

Если добавить ...

if (m_socket->bytesAvailable() < 5) 
    return; 

... в начало этой функции, приложение работает отлично (с коротким тестовым сообщением).

Я предполагаю, что тогда (документация очень редкая), что происходит какой-то тупик, и что я должен использовать сигнал bytesAvailable(), чтобы постепенно наращивать буфер, а не блокировать.

Почему это? И каков правильный подход к чтению из QLocalSocket?

ответ

2

Ваша петля блокирует цикл событий, поэтому вы никогда не получите данные, если все не были получены pn вначале, что вызывает вашу проблему, я думаю.

Правильный подход заключается в использовании сигналов и слотов, readyRead -сигнал здесь, и просто прочитайте доступные данные в своем слоте, и если их недостаточно, буферизуйте и верните и прочитайте больше, когда вы получите следующий сигнал.

Будь осторожен с этим альтернативным подходом: Если вы абсолютно уверены, что все данные, которые вы ожидаете собираются прибыть быстро (возможно, не является необоснованными с локальным сокетом, где вы контролируете клиент и сервер), или если все это находится в потоке, который ничего не делает, тогда может быть хорошо использовать метод waitForReadyRead. Но цикл событий останется заблокированным до тех пор, пока не поступят данные, например, замораживая графический интерфейс (если в потоке графического интерфейса пользователя), и, как правило, хлопотно.

+0

спасибо, мне не приходило в голову, что это было * мой * цикл блокировки (хотя я видел, как он вращался в отладчике!), А не readRawData(). – sebf