如何读取从PHP通过套接字发送到Qt服务器应用程序的字符串?

时间:2015-09-08 19:32:09

标签: php c++ qt sockets

我很难读取通过套接字连接发送到Qt服务器应用程序的字符输入。数据从PHP发送。

我理解读取streamdata的原则,因为我已经在堆栈上问过这个。我也使用在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");
}

从浏览器网址执行时脚本回复:

Socket created nConnection established nMessage send successfully n hello

2 个答案:

答案 0 :(得分:1)

您是否需要完成此任务的数据序列化?您的PHP客户端和Qt服务器可能使用不同的格式。 尝试发送和接收原始数据。

这是一个简单的QTcpServer例子:

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 :(得分:1)

PHP代码没有集成并不奇怪。如前所述,您必须知道QDataStream实现了自定义序列化。并且如前所述,如果您阅读以前未使用QDataStream进行序列化的内容,则可能需要使用(read|write)RawData(read|write)Bytes。但是,您尝试从PHP 编写字符串数据的方式的一般概念应该与Qt编码字符串的方式兼容(长度然后是一系列字符。无论如何,这是手册所说的..) 。但是有一些问题。

  • QString是2Byte Unicode。
  • PHP字符串是任意种类的ASCII兼容数据的字节数组 - PHP String details
  • 这一点有点问题:

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

    strlen()返回底层存储中的字节数(这是ASCII字符串的实际字节长度)。 base64_encode()更改字符串中的字节数。假设fwrite()正在写一个四字节整数。它的类型是铸造和写一个字符串。

  • 我们仍在猜测

    QString data; 
    in >> data;
    

    确实有效。

一般建议是,您必须仔细定义外部二进制API。