두 가지 Qt 애플리케이션이 있습니다. App1은 App2에서 QTcpServer
을 통해 연결을 허용하고 QTcpSocket* tcpSocket
의 인스턴스에 저장합니다. App1은 30Hz 시뮬레이션을 실행합니다. 각각의 시뮬레이션 실행을 위해, 몇 킬로바이트로 구성된 QByteArray
은 (주/GUI 스레드에서) 다음 코드를 사용하여 전송됩니다QTcpSocket을 사용하여 소량 데이터 패키지를 자주 보내는 방법은 무엇입니까?
QByteArray block;
/* lines omitted which write data into block */
tcpSocket->write(block, block.size());
tcpSocket->waitForBytesWritten(1);
thread)를 호출하고 해당 타임 스탬프를 GUI에 인쇄합니다.
App1과 App2가 모두 동일한 시스템에서 실행되면 패키지가 완벽하게 동기화됩니다. 그러나 App1과 App2가 네트워크를 통해 연결된 다른 시스템에서 실행될 때 App2는 App2의 시뮬레이션과 더 이상 동기화되지 않습니다. 패키지가 훨씬 느리게 들어옵니다. 더 놀라운 것은 (우리의 구현이 잘못되었음을 나타냄) 사실은 시뮬레이션 루프를 멈추었을 때 패키지가 더 이상 수신되지 않는다는 사실입니다. TCP 프로토콜에서 모든 패키지가 결국 도착할 것으로 기대하기 때문에 이것은 놀랄 일입니다.
Qt의 fortune example을 기반으로 TCP 로직을 구축했습니다. 그러나 포춘 서버는받는 클라이언트마다 하나의 패키지 만 전송하기 때문에 다릅니다. 누군가가 우리가 잘못한 것을 확인할 수 있습니까?
참고 : 우리는 MSVC2012 (App1), MSVC2010 (App2) 및 Qt 5.2를 사용합니다.
편집 : 패키지는 숫자가 많은 단일 시뮬레이션 실험의 결과를 의미하며 QByteArray block
에 기록됩니다. 그러나 첫 번째 비트에는 QByteArray의 길이가 포함되어 있으므로 클라이언트는 모든 데이터가 수신되었는지 여부를 확인할 수 있습니다. 데이터 패키지에 의해
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_5_2);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return; // cannot yet read size from data block
in >> blockSize; // read data size for data block
}
// if the whole data block is not yet received, ignore it
if (tcpSocket->bytesAvailable() < blockSize)
return;
// if we get here, the whole object is available to parse
QByteArray object;
in >> object;
blockSize = 0; // reset blockSize for handling the next package
return;
TCP 패키지/패킷이 없습니다 - 그냥 바이트 스트림이다. 어떻게 데이터를 잘라 냈습니까? 즉, 자신의 데이터 "패킷"중 하나가 시작되고 또 다른 끝이 언제 수신되는지를 애플리케이션이 어떻게 알 수 있습니까?또한 TCP에는 흐름 제어가 있으므로 데이터 읽기를 중지하면 TCP 스택의 버퍼가 가득 차고 더 이상 데이터가 전송되지 않습니다 (소켓이 비 블로킹 모드가 아닌 경우 송신하려고하면 송신자가 차단됩니다). 그러나 우리가 당신이 무엇을하는지, 어떻게 시뮬레이션이 작동하는지 또는 어떤 식으로 어떻게 동기화되지 않는지를 알지 못할 때 당신이 잘못한 것을 추측하는 것은 매우 어렵습니다. – nos
원래 질문을 편집하여 질문에 대답하려고했습니다. 좀 봐주세요. –
당신이 원하는 것보다 더 많은 데이터를 읽는 것 같습니다. 당신의 블록 사이즈는 1024이지만'tcpSocket-> bytesAvailable()'은 1222 바이트를 사용할 수 있습니다. 다음 블록의 시작 부분도 보입니다. 그래서'in.readBytes() '를 사용해야 할 것입니다. '대신 읽는 양을 지정할 수 있습니다. (그리고 실제로 많은 양의 데이터를 읽었 음을 나중에 확인하십시오.) 그러나 그것은 또한 프로토콜이 어떤지에 달려 있습니다. 예를 들어 그것은 단순한 요청/응답입니다. 송신자가 이전 패킷에 대한 응답을받을 때까지 데이터를 보내지 않습니다. 현재 코드는 OK입니다. – nos