应该如何读取QLocalSocket/QDataStream以避免死锁

How should QLocalSocket/QDataStream be read to avoid deadlocks?

本文关键字:QDataStream 死锁 QLocalSocket 何读取 读取      更新时间:2023-10-16

QLocalSocket/QDataStream应该如何读取?

我有一个程序,它使用 QLocalSocketQDataStream 通过命名管道与另一个程序进行通信。下面的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读取的正确方法是什么?

您的循环会阻止事件循环,因此如果所有数据都没有到达 pn 第一次读取,您将永远不会获得数据,我认为这是导致您的问题的原因。

正确的方法是使用信号和插槽,在这里readyRead -signal,然后读取插槽中的可用数据,如果没有足够的数据,则缓冲并返回,并在获得下一个信号时读取更多。

小心这种替代方法:如果您绝对确定您期望的所有数据都会及时到达(对于您同时控制客户端和服务器的本地套接字来说可能并非不合理),或者如果整个事情都在线程中,没有其他内容,那么使用waitForReadyRead方法可能是可以的。但是事件循环将保持阻塞状态,直到数据到达,例如冻结 GUI(如果在 GUI 线程中),并且通常很麻烦。