Как мне прочитать строку, отправленную из PHP через сокет в приложение сервера Qt?

Мне очень трудно читать ввод символов, который отправляется через сокет-соединение с приложением Qt-сервера. Данные отправляются с PHP.

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

Метод, который я использую, заключается в добавлении байта данных, которые я хочу отправить, до фактических данных. Затем, когда поступают данные, я сначала читаю parth длины, чтобы точно знать, сколько байтов мне нужно прочитать, чтобы получить правильно сформированные данные.

это выглядит так:

отправить функцию:

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);
out  << string;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

tcpSocket->write(block);
}

получить функцию:

QDataStream in(tcpServerConnection);
in.setVersion(QDataStream::Qt_4_0);
qDebug() << "bytes available = " << tcpServerConnection->bytesAvailable();

if (blockSize == 0) {
int size = (int) sizeof(quint16);
qDebug() << "size = " << size;
if (tcpServerConnection->bytesAvailable() < (int)sizeof(quint16)){
qDebug() << "less bytes than size...";
return;
}
qDebug() << "bytes available=" << tcpServerConnection->bytesAvailable();
in >> blockSize;
}

if (tcpServerConnection->bytesAvailable() < blockSize){
qDebug() << "less bytes available than blocksize, bytes="<< tcpServerConnection->bytesAvailable();
return;
}

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

Хорошо, все это работает, поэтому я попытался сделать это с PHP, но это не удалось

это одна из моих попыток:

<?php

$addr = gethostbyname("127.0.0.1");

$client = stream_socket_client("tcp://$addr:*****", $errno, $errorMessage);

if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}

$data = 'a';
$datatopost = serialize($data);

fwrite($client, strlen($data));
fwrite($client, base64_encode($data));
echo stream_get_contents($client);
fclose($client);

В Qt я пробовал различные комбинации quint8, 16, 32, 64, sizeof (char), sizeof (int).

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

Задав различные вопросы по этой теме, я чувствую, что мое понимание сильно возросло, но важная информация о том, как на самом деле делать вещи, все еще отсутствует для меня.

Итак, мой вопрос: что здесь не так и какие шаги нужно предпринять, чтобы иметь возможность читать данные из PHP в Qt / C ++?

Детали высоко ценятся, так как мне очень нравится знать, как все работает изнутри.

Примечание после отправки данных из PHP-сценария сервер отправляет данные обратно aswel, и это работает. Таким образом, соединение установлено успешно

ОБНОВИТЬ
это рабочий скрипт php, который на самом деле также получает ответ:

<?php

if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
perror("Could not create socket");
}
echo "Socket created n";

//Connect socket to remote server
if(!socket_connect($sock , '127.0.0.1' , *****))
{
perror("Could not connect");
}
echo "Connection established n";

$message = "aa";
//Send the message to the server
if( ! socket_send ( $sock , $message , strlen($message) , 0))
{
perror("Could not send data");
}
echo "Message send successfully n";

//Now receive reply from server
if(socket_recv ( $sock , $buf , 500 , MSG_WAITALL ) === FALSE)
{
perror("Could not receive data");
}
echo $buf;

///Function to print socket error message
function perror($msg)
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);

die("$msg: [$errorcode] $errormsg n");
}

Ответ скрипта при выполнении из URL браузера:

Socket created nConnection established nMessage send successfully n hello

1

Решение

Не удивительно, что код PHP не интегрируется. Как уже упоминалось, вы должны знать, что QDataStream реализует пользовательскую сериализацию. И, как уже упоминалось, вы, вероятно, хотите использовать (Чтение | запись) RAWDATA, или же (Чтение и запись) | Bytes, если вы читаете что-то, что ранее не сериализовано с QDataStream вообще. Тем не менее, общая идея о том, как вы пытаетесь записать строковые данные из PHP должен быть совместимым с тем, как Qt кодирует строки (длина, то есть серия символов. Так и есть в руководстве). Но есть некоторые проблемы.

  • QString это 2Byte Unicode.
  • Строки PHP — это байтовые массивы произвольного вида ASCII-совместимых данных — Детали PHP строки.
  • Есть несколько вещей не так с этим битом:

    fwrite($client, strlen($data));
    fwrite($client, base64_encode($data));
    

    strlen() возвращает количество байтов в базовом хранилище (которое является фактической длиной байта для строки ASCII). base64_encode () изменяет количество байтов в строке. И вы предполагаете, что fwrite () записывает четырехбайтовое целое число. Его тип приведения и написания строки.

  • Мы все еще гадаем, как

    QString data;
    in >> data;
    

    действительно работает.

Общий совет: вы должны тщательно определить внешние двоичные API.

1

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

Вам нужна сериализация данных для этой задачи вообще? Ваш PHP-клиент и Qt-сервер, вероятно, используют для этого разные форматы.
Попробуйте отправить и получить необработанные данные.

Вот простой QTcpServer exmaple:

class DataReceiver : public QObject
{
Q_OBJECT
public:
explicit DataReceiver(QObject *parent = 0);

public slots:
void start(quint16 port = 9090);

private slots:
void newTcpConnection();

private:
QTcpServer server;
};

DataReceiver::DataReceiver(QObject *parent) :
QObject(parent)
{
connect(&server, SIGNAL(newConnection()), this, SLOT(newTcpConnection()));
}

void DataReceiver::start(quint16 port)
{
bool isOk = server.listen(QHostAddress::Any, port);

if (isOk && server.isListening())
{
qDebug() << "QTcpServer started on port" << port;
}
else
{
qCritical() << "Failed to start QTcpServer";
}
}

void DataReceiver::newTcpConnection()
{
qDebug() << "New incoming connection";

QTcpSocket *socket = server.nextPendingConnection();

QByteArray data;

while (true)
{
QByteArray tmp = socket->readAll();
data += tmp;

if (tmp.isEmpty() && !socket->waitForReadyRead())
{
break;
}
}

socket->deleteLater();

qDebug("Data received: %s (len = %d)", data.constData(), data.length());
}

Запуск сервера:

#include <QCoreApplication>

#include "data_receiver.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

DataReceiver d;
d.start();

return a.exec();
}

Вы можете использовать PHP-клиент для отправки данных:

<?php

$addr = gethostbyname("127.0.0.1");
$port = 9090;
$data = 'hello from php';

$client = stream_socket_client("tcp://$addr:$port", $errno, $errorMessage);

if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}

fwrite($client, $data);
fclose($client);

Или вы можете использовать nc полезность:

echo -n "hello from nc" | nc 127.0.0.1 9090

Вот выходные данные сервера для обоих случаев:

QTcpServer started on port 9090
New incoming connection
Data received: hello from php (len = 14)
New incoming connection
Data received: hello from nc (len = 13)
1

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