php - 通过套接字发送数据的过程到底是如何工作的?

标签 php c++ qt sockets stream

我已经编写了一个可以来回发送字符串的服务器/客户端设置,并且可以正常工作。现在我正尝试从一个不起作用的 php 脚本发送数据,所以我试图弄清楚为什么它不起作用。

这是从客户端发送数据的代码,我发送到服务器的字符串=“aa”

(注意代码中的注释)

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编写的。

最佳答案

TCP 是一种字节流 协议(protocol),这意味着在不保留任何逻辑消息边界的情况下,以有序的字节流发送和接收数据。在这方面,读取数据有点像读取 std::cin。当您的终端设置为无缓冲模式时:您可能会收到用户键入的下一个字符,或 10 个字符,或整行、一行半或下一个 4k。关于您唯一可以确定的是,您无法获得比写入流更多的内容。当你有足够的数据来进行有意义的处理时,这取决于你:这可能是...

  • 扫描哨兵字符,如 '\n' ,知道完整的输入行是值得处理的不同“逻辑”消息

  • 为下一个逻辑消息预置长度,可以是固定长度字段(更简单)或可变长度文本,后跟已知分隔符,例如空格或换行符;这就是您的代码对 2 字节 quint16 所做的事情size值(value)

  • 将每个逻辑消息填充到固定长度

然后有必要保留 read()荷兰国际集团或recv()直到读取了足够的字节供您处理下一条逻辑消息。

看来你的QDataStream read() 让您更轻松荷兰国际集团/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”值,它通过从 block 中减去 2 个字节来确定。尺寸。

在服务器端,似乎每次接收到更多数据时都会调用该函数,并将检查是否有足够的数据作为下一条消息进行解析。虽然它看起来有问题,好像有足够的数据来解析 size但是整个字符串还没有被缓冲,然后它返回并在这样做时丢弃所有关于 blockSize 的知识。 ,它已经从 QDataStream 中删除了.相反,它应该记住 blockSize某处(例如在类成员变量中),下次调用该函数时,它应该从 if (tcpServerConnection->bytesAvailable() < blockSize) 继续.

关于php - 通过套接字发送数据的过程到底是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32447800/

相关文章:

PHP PDO fetchAll、PDO::FETCH_CLASS 和连接

php - Symfony 关于 Apache 权限问题

c++ - 无效的数组分配

c++ - QTest异步信号拦截

c++ - 函数指针的分支预测

c++ - Qt5 : could not connect signal to slot

linux - `root` 先前运行应用程序后,QSerialPort 无法打开 tty

php - 如何使用 PHP 反射来设置静态属性?

PHP强制下载显示网络错误

qt - ffmpeg "dynamic"图像叠加