http://www.qt-forum.de/forum/viewtopic.php?t=6769
Ich verschicke ein QByteArray, das beim Empfänger nur bruchstückhaft ankommt.
Der Code für die Senderseite ist folgender:
message ist der eigentliche Inhalt, die ganzen IDs und Groups sind quint16, die dann vorne an die Nachricht angehängt werden (der Server leitet die Nachrichten entsprechend weiter, sprich er vermittelt nur). Ganz an den Anfang habe ich eine quint32 gesetzt, die die Gesamtlänge der Nachricht enthält, headerSize ist für die IDs und ist 4*sizeof(quint16). Sollte alles soweit klar sein:
Code: Alles auswählen
void EventClient::sendMessage(QByteArray message, quint16 receiverID, quint16 receiverGroup)
{
QByteArray msg;
QDataStream buffer(&msg, QIODevice::WriteOnly);
buffer << quint32(VRGUI::headerSize + message.size());
buffer << quint16(connection.ID);
buffer << quint16(connection.group);
buffer << quint16(receiverID);
buffer << quint16(receiverGroup);
buffer << message;
connection.socket->write(msg);
}Der Server arbeitet den Socket nun nicht mit einer Connection zum readyRead-signal, sondern über eine eigene Tick-Schleife ab, in der jedes mal für alle verbundenen Clients geprüft wird, ob neue Daten verfügbar sind. Hoffe, dass der Source mit den Kommentaren ausreichend ist:
Code: Alles auswählen
void EventServer::slotTimerTick()
// The main message processing function of the server.
// Reads and dispatches messages and checks for system requests.
{
// process clients - read messages from client connections
foreach(EventConnection* tmpConnection, clientList)
{
if(tmpConnection->socket->bytesAvailable())
{
// fist check if the connection is in ready mode. This means hat no message is currently being
// received, so that any new data is a new message header. This header data is read if it has been
// recieved completly (VRGUI::headerSize + sizeof(quint64)).
if (
(tmpConnection->status == VRGUI::connectionReady)
&& tmpConnection->socket->bytesAvailable() >= VRGUI::headerSize + sizeof(quint64)
)
{
QDataStream tmpStream(tmpConnection->socket);
tmpStream >> tmpConnection->msg.totalSize;
tmpStream >> tmpConnection->msg.senderID;
tmpStream >> tmpConnection->msg.senderGroup;
tmpStream >> tmpConnection->msg.receiverID;
tmpStream >> tmpConnection->msg.receiverGroup;
tmpConnection->msg.totalSize -= VRGUI::headerSize; // subtract this as usually the header is part of the total message size
tmpConnection->status = VRGUI::connectionTransmitting; // set the new status to show that message data is being read
}
// if data is being received (i.e. the message was not read completly during the last tick), it is
// read from the socket and appended to the already received bytes. This continues until all data is read.
if (tmpConnection->status == VRGUI::connectionTransmitting)
{
int bytesStillMissing = tmpConnection->msg.totalSize - tmpConnection->messageInProgress.size();
tmpConnection->messageInProgress.append(tmpConnection->socket->read(bytesStillMissing));
if(tmpConnection->msg.totalSize == tmpConnection->messageInProgress.size())
// if all message data is read, it is stored in the msg.messageContent and this msg is appended
// to the message queue which will be used in a later loop to dispatch all finished messages.
{
QDataStream tmpStream(tmpConnection->messageInProgress);
tmpStream >> tmpConnection->msg.messageContent;
messageList.append(tmpConnection->msg);
clearMessage(tmpConnection->msg); //clearMessage clears the msg struct so that it is re-initialized and empty for the next run
tmpConnection->messageInProgress.clear(); // erase contents of the temp message content, reason same as above
tmpConnection->status = VRGUI::connectionReady; // connection status is set back to ready, the connection can read new messages now
}
}
}
}
}Code: Alles auswählen
while(tmpConnection->socket->bytesAvailable())
{
QDataStream tmpStream(tmpConnection->socket);
QByteArray tmpData;
MessageStruct tmpStruct;
tmpStream >> tmpStruct.totalSize;
tmpStream >> tmpStruct.senderID;
tmpStream >> tmpStruct.senderGroup;
tmpStream >> tmpStruct.receiverID;
tmpStream >> tmpStruct.receiverGroup;
tmpStream >> tmpStruct.messageContent;
messageList.append(tmpStruct);
} Und zum Schluß noch 2 kurze Fragen:
In der QT-Doku ist von einem "Short-Read" beim Zugriff auf Sockets die Rede. Ist das eine Leseanweisung, bei der mehr Bytes gelesen werden sollen, als verfügbar sind? Habe dazu nichts gefunden.
Und als letztes gibt mit VS beim debuggen für 4*sizeof(quint16) den Wert 16 an. Nach meinem Verständnis ist das aber 8, denn quint16 hat 2 Byte und das dann mal 4 ist 8. Kann das jemand aufklären?