“连接关闭”当使用 QNetworkAccessManager 和 QTcpServer

Posted

技术标签:

【中文标题】“连接关闭”当使用 QNetworkAccessManager 和 QTcpServer【英文标题】:"Connection closed" When using QNetworkAccessManager and QTcpServer 【发布时间】:2016-10-20 10:27:04 【问题描述】:

我有带有 QTcpServer 的简单服务器和带有 QNetworkAccessManager 的简单客户端。

    当我通过 curl 或浏览器向服务器请求数据时,一切正常 当我通过 QNetworkAccessManager 从任何站点请求数据时,一切正常 但我无法通过 QNetworkAccessManager 从 QTcpServer 读取数据。所有请求都被重置。 QNetworkAccessManager(客户端)在收到来自服务器的数据后立即发送 RST(重置连接)。在客户端代码中,我们收到错误:“连接已关闭”(RemoteHostClosedError) 另外,我尝试使用 DownloadManager 示例中的 QNetworkAccessManager 和 FortuneServer 示例中的 QTcpServer 进行各种组合,但结果是相同的。

经过测试的 Qt 版本:

Mac Qt 5.7 Linux Qt 5.7 Linux Qt 5.6.2 Linux Qt 5.5.1

Wireshark 截图:qt-wireshark.png 上半部分(红线部分)是 QNetworkAccessManager 的结果,最新成功的数据包是 curl 尝试从 QTcpServer 获取数据

还有一个简单的例子可以重现错误:testNetwork.zip

这里是客户端的示例代码:

void test(quint16 port)

    QNetworkAccessManager *manager = new QNetworkAccessManager();

    QNetworkRequest request;
    request.setUrl(QUrl(QString("http://127.0.0.1:%1/").arg(port)));

    manager->connect(manager, &QNetworkAccessManager::finished,
                     [](QNetworkReply *reply) 
        qDebug() << QString("Finished. %1. %2").arg(reply->errorString()).arg(reply->error());
        qDebug() << "readed: " << reply->readAll();
    );

    QNetworkReply *reply = manager->get(request);

    reply->connect(reply, &QNetworkReply::readyRead, [reply]() 
        qDebug() << QString("readyRead: '%1'").arg(QString(reply->readAll()));
    );

对于服务器:

QTcpSocket socket;
...
if(socket.waitForReadyRead(5000))

    QByteArray request;
    request += socket.readAll();

    QByteArray responce("HELLO, WORLD! HELLO, WORLD! HELLO, WORLD! HELLO, WORLD!");

    socket.write(responce);
    if(!socket.waitForBytesWritten())
    
        qWarning() << QString("Error occurred in waitForBytesWritten() method of the tcp socket. %1 (%2)")
                      .arg(socket.errorString())
                      .arg(socket.error());
    

else

    qWarning() << QString("Error occurred in read method of the tcp socket. %1 (%2)")
                  .arg(socket.errorString())
                  .arg(socket.error());

我还在 qt.io (QTBUG-56631) 上创建了一个错误报告

【问题讨论】:

【参考方案1】:

您的客户端正在发出 HTTP 请求,但您的服务器不是 http 服务器 - 它没有发回有效的 HTTP 请求。

当您将客户端指向 Web 服务器时,它就可以工作,因为那是一个 http 服务器。

    QByteArray responce("HELLO, WORLD! HELLO, WORLD! HELLO, WORLD! HELLO, WORLD!");

不是有效的 HTTP 响应。

【讨论】:

我要感谢 Qt Forum 上的 raven-worx 的回复: 他的回复:至少回复应该如下所示。注意:每行应以 \r\n 结尾,空行分隔 header- 和 content-section Content-Length 标头是内容的字节数 HTTP/1.1 200 OK 日期:Thu, 20 Oct 2016 12:28: 53 GMT 服务器:MyServer 1.0.0 内容长度:3 内容类型:文本/纯文本连接:已关闭 XXX

以上是关于“连接关闭”当使用 QNetworkAccessManager 和 QTcpServer的主要内容,如果未能解决你的问题,请参考以下文章

检测非阻塞套接字上的关闭连接

pgjava连接关闭

连接池

jetty 9,websockets 和关闭服务器端的 websocket 连接

数据库连接池(DBUtils)

java.sql.SQLException:连接关闭后不允许任何操作