我已经看到了几个用于服务器发送事件的库,不幸的是,没有用于 Qt。我还查看了 SSE 的规范(只是普通的 HTTP),似乎在 Qt 中实现 SSE 需要:
application/events-streamdata : {...})我不确定它是否那么“容易”?我错过了什么?
我用 Qt 和 Server Sent Events 创建了一个小演示。该演示连接到给定的 EventSource URL(第一个参数)并将每个事件打印到命令行。
Qt 支持开箱即用的 SSE,因为 SSE 是纯 HTTP,在它上面有一个重新连接层。
text/event-stream接受标头,允许重定向,禁用缓存。QNetworkRequest Network::Manager::prepareRequest(const QUrl &url)
{
    QNetworkRequest request(url);
    request.setRawHeader(QByteArray("Accept"), QByteArray(ACCEPT_HEADER));
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); // Events shouldn't be cached
    return request;
}
Run Code Online (Sandbox Code Playgroud)
readyRead信号连接到插槽。void Network::Manager::getResource(const QUrl &url)
{
    qDebug() << "GET resource:" << url;
    QNetworkRequest request = this->prepareRequest(url);
    m_reply = this->QNAM()->get(request);
    connect(m_reply, SIGNAL(readyRead()), this, SLOT(streamReceived()));
}
Run Code Online (Sandbox Code Playgroud)
readAll. 我们在每次成功事件后重置重试计数器。void Network::Manager::streamReceived()
{
    qDebug() << "Received event from stream";
    qDebug() << QString(m_reply->readAll()).simplified().replace("data: ", "");
    qDebug() << "-----------------------------------------------------";
    m_retries = 0;
}
Run Code Online (Sandbox Code Playgroud)
finished()QNetworkAccessManager 会触发信号。我们尝试重新连接到事件源(我们在创建 QNetworkAccessManager 实例时将此插槽连接到信号):void Network::Manager::streamFinished(QNetworkReply *reply)
{
    qDebug() << "Stream finished:" << reply->url();
    qDebug() << "Reconnecting...";
    if(m_retries < MAX_RETRIES) {
        m_retries++;
        this->getResource(reply->url());
    }
    else {
        qCritical() << "Unable to reconnect, max retries reached";
    }
}
Run Code Online (Sandbox Code Playgroud)
你可以在这里找到演示:https : //github.com/DylanVanAssche/Qt-Server-Sent-Events-Demo