Почему QTcpSocket получил неверные данные?

Я пишу простое сетевое приложение. Клиент отправляет на сервер сообщений сервер, распечатывая его в QTextEdit и отвечая клиенту.
Я использую QTcpServer и QTcpSocket.
Есть проблема, которую я не могу решить. Прием данных — это quint16 + QTime + QString, который отправляется как QByteArrey.
Я использую quint16 для получения размера блоков данных. И по какой-то причине, когда клиент отправляет на сервер

next block size: 16 (quint16 value)
block size: 18

Сервер получить:

next block size: 30073  (quint16 value)
block size: 18

Как видите, по какой-то причине сервер получает из QDataStrem неверное значение переменной, и оно всегда равно 30073. Я не понимаю, почему?

void Widget::slotSendToServer()
{
logTextEdit->append("slotSendToServer()");
QByteArray arrBlock;
QDataStream serverSendStream(&arrBlock, QIODevice::ReadWrite);
QString messageStr = messageLineEdit->text();

serverSendStream << quint16(0) << QTime::currentTime()
<< messageStr;

serverSendStream.device()->seek(0);
serverSendStream << (quint16)(arrBlock.size() - sizeof(quint16));

qDebug() << "next_block_size:"<<(quint16)(arrBlock.size() - sizeof(quint16))
<< endl
<< "full size of Byte arrey:" << arrBlock.size();

tcpSocket->write(arrBlock);
messageLineEdit->clear();
}void Widget::slotReadClient()
{
logTextEdit->append("slotReadClient()");
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
QDataStream clientReadStream(tcpSocket);

while(true)
{
if (!next_block_size)
{
if (tcpSocket->bytesAvailable() < sizeof(quint16))
{
break;
}
clientReadStream >> next_block_size;
}

if (tcpSocket->bytesAvailable() < next_block_size)
{
break;
}
QTime   time;
QString messageTextStr;
clientReadStream >> time >> messageTextStr;

QString messageCompleteStr =
time.toString() + " " + "Client has sent - "+ messageTextStr;
logTextEdit->append("Message received: ");
logTextEdit->append(messageCompleteStr);

next_block_size = 0;

sendToClient(tcpSocket,
"Server Response: Received \""+ messageTextStr + "\"");
}
}

0

Решение

Вы должны убедиться, что переменная next_block_size устанавливается в 0 каждый раз при подключении сокета.

Если вы не используете то же самое QTcpSocket объект, это может быть сделано в вашем Widget конструктор класса, или, если вы делаете, в слоте, подключенном к сигналу connected(),

2

Другие решения

Я понятия не имею, почему ты сделал это так сложно.
Это должно работать:

void Widget::slotSendToServer()
{
logTextEdit->append("slotSendToServer()");
QByteArray arrBlock;
QDataStream serverSendStream(tcpSocket);

serverSendStream << QTime::currentTime()
<< messageLineEdit->text();
messageLineEdit->clear();
}

void Widget::slotReadClient()
{
logTextEdit->append("slotReadClient()");
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
QDataStream clientReadStream(tcpSocket);

QTime time;
QString message;

clientReadStream >> time >> message;

emit YourSignal(time, message);
}

Вам не нужно беспокоиться о размерах, QDataStream отслеживает это, вам нужно только поддерживать ту же последовательность чтения, что и при записи, поэтому ваш буфер arrBlock это пустая трата кода.


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

Что касается вашего кода, вы наверняка испортили читателя с циклом while, так что здесь исправление без этого цикла.

void Widget::slotReadClient()
{
logTextEdit->append("slotReadClient()");
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
QDataStream clientReadStream(tcpSocket);

if (next_block_size==0) {
// need to read data size
if (tcpSocket->bytesAvailable() < sizeof(quint16))
return; // wait for next signal
// next_block_size must be type of qint16
clientReadStream >> next_block_size;
}
if (tcpSocket->bytesAvailable() < next_block_size) {
// not enought data to complete read immediately
return;  // wait for next signal
}
QTime time;
QString messageTextStr;
clientReadStream >> time >> messageTextStr;
QString messageCompleteStr =
time.toString() + " " + "Client has sent - "+ messageTextStr;
logTextEdit->append("Message received: ");
logTextEdit->append(messageCompleteStr);

// mark that data read has been finished
next_block_size = 0;
}
-1

По вопросам рекламы [email protected]