Как на самом деле работает процесс отправки данных через сокет?

Я написал настройку сервера / клиента, которая может отправлять строки туда и обратно, и это работает. Теперь я пытаюсь отправить данные из php-скрипта, который не работает, поэтому я пытаюсь выяснить, почему именно это не будет работать.

Это код отправки данных от клиента, строка, которую я отправляю на сервер = «аа»

(обратите внимание на комментарии в коде)

void Client::sendNewMessage(){
qDebug() << "sendNewMessage()";

QString string(messageLineEdit->text());

QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << quint16(0) << string; // why is the quint16 appended before the string?
out.device()->seek(0); // set current position to 0, why exactly?
out << (quint16)(block.size() - sizeof(quint16)); // substract 16bit unsigned int from the total data size?
//Probably something to do with the appending of the quint16 at the beginning.

tcpSocket->write(block);
}

и это функция чтения для сервера:

void TcpServer::readIncomingData(){
QDataStream in(tcpServerConnection);
in.setVersion(QDataStream::Qt_4_0);

int size = (int) sizeof(quint16); // get packetsize? size = 2 because quint16 is 2 bytes?
qDebug() << "size = " << size;

// ** OPTIONAL CODE, WORKS WITHOUT ASWELL ** // I got this somewhere from the internet.
if (tcpServerConnection->bytesAvailable() < (int)sizeof(quint16))
return; // if size of packet is less than 2, return.
// Because there is not enough bytes to correctly read the data?

quint16 blockSize = 0;
in >> blockSize; // i noticed that after this line executes
// tcpServerConnection->bytesAvailable is substracted by 2
// and blockSize = 8 instead of 10, because
// tcpServerConnection->bytesAvailable starts with 10.
// it seems that the socket recognizes that a quint16 was appended
// before the actual data, hence the 8 bytes. Is this correct?

if (tcpServerConnection->bytesAvailable() < blockSize)
return;

QString data;
in >> data;
qDebug() << "data = " << data;

Таким образом, основная цель этих вопросов — иметь возможность отправлять данные из сценариев PHP на сервер, поэтому мне нужно (и нужно) знать, как именно работает весь этот процесс. Я был бы рад, если бы кто-то мог пролить свет на эту черную дыру: D

НОТА сервер и клиент написаны с использованием QTcpSocket и QTcpServer.

0

Решение

TCP является поток байтов протокол, который означает, что данные отправляются и принимаются в виде упорядоченного потока байтов без сохранения каких-либо логических границ сообщения. В этом отношении чтение данных немного похоже на чтение std::cin когда ваш терминал установлен в небуферизованный режим: вы можете получить следующий набранный пользователем символ, или 10 символов, или полную строку, строку с половиной или следующие 4k. Единственное, в чем вы можете быть уверены, это то, что вы не можете получить больше, чем было записано в поток. Вам решать, когда у вас достаточно данных для полноценной обработки: это может быть …

  • сканирование для сторожевого персонажа, как '\n'зная, что полные строки ввода — это отдельные «логические» сообщения, которые стоит обработать

  • добавление длины для следующего логического сообщения в виде поля фиксированной длины (проще) или текста переменной длины, за которым следует известный разделитель, такой как пробел или символ новой строки; это то, что ваш код делает с 2-байтовым quint16 size значение

  • заполнение каждого логического сообщения фиксированной длиной

Тогда необходимо сохранить read()или recv()до тех пор, пока не будет прочитано достаточно байтов для обработки следующего логического сообщения.

Кажется твой QDataStream делает это легче для вас read()ING /recv()в любое время — возможно, в фоновом потоке или когда ваше приложение бездействует. Это очевидно обеспечивает bytesAvailable() как количество байтов, которые он уже получил из потока TCP и имеет в своем буфере.

На стороне клиента:

QString string(messageLineEdit->text());
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << quint16(0) << string; // why is the quint16 appended before the string?

Это записывает 2-байтовое значение «0», за которым следует текст из string, Первый эффективно резервирует пространство для длины string,

out.device()->seek(0); // set current position to 0, why exactly?

Это пропускает назад перед строкой туда, где 2-байтовое значение «0» было написано выше …

out << (quint16)(block.size() - sizeof(quint16)); // substract 16bit unsigned int from the total data size?

Это заменяет записанное выше значение «0» фактическим размером строки, которое определяется вычитанием 2 байтов из block размер.

На стороне сервера это выглядит так, как будто функция предназначена для вызова при каждом получении большего количества данных, и проверит, достаточно ли данных для анализа в качестве следующего сообщения. Это выглядит глючно, хотя, как будто есть достаточно данных, чтобы разобрать size но вся строка еще не была буферизована, затем она возвращается и при этом отбрасывает все знания о blockSizeкоторый будет уже удален из QDataStream, Вместо этого следует помнить, что blockSize где-нибудь (например, в переменной члена класса), и в следующий раз, когда вызываемая функция будет продолжать if (tcpServerConnection->bytesAvailable() < blockSize),

2

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector