Я пишу простое сетевое приложение. Клиент отправляет на сервер сообщений сервер, распечатывая его в 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 + "\"");
}
}
Вы должны убедиться, что переменная next_block_size
устанавливается в 0 каждый раз при подключении сокета.
Если вы не используете то же самое QTcpSocket
объект, это может быть сделано в вашем Widget
конструктор класса, или, если вы делаете, в слоте, подключенном к сигналу connected()
,
Я понятия не имею, почему ты сделал это так сложно.
Это должно работать:
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;
}