2014-02-11 2 views
1

간단한 QLocalServer-QLocalSocket IPC 시스템을 설계 할 때 문제가 발생합니다.Qt 5.2 : QLocalServer가 readyRead 신호를 중복 받음

QLocalServer는 새 연결을 기다리고 해당 슬롯에 신호를 연결합니다.

void CommandProcessor::onNewConnection() 
{ 
    QLocalSocket* pLocal = _server->nextPendingConnection(); 

    connect(pLocal,SIGNAL(disconnected()),this,SLOT(onSocketDisconnected())); 
    connect(pLocal,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead())); 
    connect(pLocal,SIGNAL(error(QLocalSocket::LocalSocketError)),this, SLOT(onSocketError(QLocalSocket::LocalSocketError))); 

    qDebug("Socket connected. addr=%p", pLocal); 
} 

The readyRead slot implementation is: 

void CommandProcessor::onSocketReadyRead() 
{ 
    QLocalSocket* pLocalSocket = (QLocalSocket *) sender(); 
    qDebug("SocketReadyRead. addr=%p", pLocalSocket); 

    QDataStream in(pLocalSocket); 
    in.setVersion(QDataStream::Qt_5_2); 
    pLocalSocket->readAll(); 


    qDebug("%s pLocalSocket->bytesAvailable() = %d", Q_FUNC_INFO, pLocalSocket->bytesAvailable()); 
} 

이 READALL은 (나는 것을 확인 동일한 슬롯 포인터에서) 내가 순서대로 두 readyRead 신호를 받고 있어요 방법을 확인하기 위해 의도적으로을 수행합니다.

클라이언트 조작은 매우 간단합니다 :

QByteArray data; 
    QDataStream out(&data, QIODevice::ReadWrite); 
    out.setVersion(QDataStream::Qt_5_2); 

    cmd.toDataStream(out); 

    // write blocksize at first field 

    out.device()->seek(0); 
    out << data.size() - sizeof(BLOCKSIZE_T); 
    qint64 bw = _socket->write(data); 

_socket-> 쓰기 (데이터) 호출 (서버 측이 ReadAll 메쏘드 호출로 모든 데이터를 읽을에도) 서버에서 readyRead 중복 트리거합니다.

어디서 볼 수 있습니까?

답변

2

QIODevice의 의미는 readyRead 신호는 단순히 읽을 수있는 가능성있는 데이터가 있음을 의미합니다. 확실하게 사용할 수있는 데이터라는 의미는 아니며 특정 양의 데이터를 사용할 수 있음을 의미하지는 않습니다. 구현은 가짜 신호를 피하기 위해 최선을 다하지만, 임의의 수의 "가짜"신호를 자유롭게 발급 할 수 있습니다. readyRead 시그널을 놓친다면 그것은 훨씬 더 심각한 문제가 될 것입니다 (사실 버그입니다).

당신이해야 할 일은 신호를 받았을 때 사용할 수있는 데이터를 읽는 것입니다. 그게 다야. 특정 "덩어리"에서 데이터를 얻을 수 있다는 보장은 절대적으로 없습니다. 예를 들어, 연결의 한쪽 끝이 단일 1kByte 쓰기를 수행하는 경우, 연결의 다른 쪽 끝은 readyRead 신호의 수를 얻을 수 있습니다.

보장 모든 것을

읽기 데이터 당신이 readyRead 신호를 얻을 때, 당신은 어떤 데이터를 놓치지 않을 것입니다 - 따라서 당신은 어디에서 읽어하지만 슬롯이 readyRead에 연결 할 필요가 없습니다 신호.

그래서,보고있는 것은 완벽합니다. readyRead이 발생하면 사용할 수있는 데이터의 양을 처리해야합니다. 0 바이트 포함.

+0

* "신호 *를받을 때 사용할 수있는 데이터를 읽는 것이 무엇을 의미합니까, 선택 사항도 아닙니다. 더 많은 데이터가있을 때 새로운 신호를 얻게 될 것이므로 * bytesAvailable() *을 확인하고 읽지 않고 더 기다려야합니다. 수동 버퍼링을 피하기 위해 편리합니다. – hyde

+0

@hyde 버퍼링이 무한대로 설정되면 선택 사항입니다. 기기별로 다릅니다. –

+2

@hyde'readyRead' 연결 슬롯에있는 모든 데이터를 읽지 않는다면, 언젠가는 나중에 읽을 것을 확신해야합니다. 타이머를 설정해야합니다. 더 많은 데이터가 없으면 다른 신호를받을 수 있습니다. 따라서,'readyRead'에서 모든 데이터를 읽어야하는 관용구입니다. –