简体   繁体   English

Qt服务器发送事件(SSE)

[英]Server Sent Events (SSE) with Qt

I already saw several libraries for Server Sent Events, unfortunately, not for Qt. 不幸的是,我已经看到了几个用于服务器发送事件的库,而不是Qt。 I also looked at the specification of SSE (just plain HTTP) and it seems that implementing SSE in Qt would require to: 我还查看了SSE(仅是纯HTTP)的规范,似乎在Qt中实现SSE需要:

  • Use QNetworkAccessManager in streaming mode (download) 在流模式下使用QNetworkAccessManager(下载)
  • Accept the content type header of SSE: application/events-stream 接受SSE的内容类型标头: application/events-stream
  • Reconnect when the connection is lost or closed 连接断开或关闭时重新连接
  • Attach a slot to the QNAM when new bytes are received (check for data : {...} ) 收到新的字节后,将插槽附加到QNAM(检查data : {...}

I'm not sure if it's so "easy"? 我不确定它是否那么“简单”? Did I miss something? 我错过了什么?

I created a small demo with Qt and Server Sent Events. 我使用Qt和服务器发送事件创建了一个小型演示。 The demo connects to a given EventSource URL (first argument) and prints every event to the command line. 该演示连接到给定的EventSource URL(第一个参数),并将每个事件打印到命令行。

Qt supports SSE out of the box since SSE is pure HTTP with a reconnection layer on top of it. Qt开箱即用地支持SSE,因为SSE是纯HTTP,并在其顶部具有重新连接层。

  1. Prepare the request: set the text/event-stream accept header, allow redirects, disable the cache. 准备请求:设置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;
}
  1. Connect the readyRead signal to a slot. 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()));
}
  1. Every time a new event is received by the QNetworkAccessManager, you can read it using readAll . 每次QNetworkAccessManager收到新事件时,您都可以使用readAll读取它。 We reset the retries counter after every successful event. 每个成功事件后,我们都会重试重试计数器。
void Network::Manager::streamReceived()
{
    qDebug() << "Received event from stream";
    qDebug() << QString(m_reply->readAll()).simplified().replace("data: ", "");
    qDebug() << "-----------------------------------------------------";
    m_retries = 0;
}
  1. In case we lost the connection or the connection times out, the finished() signal is triggered of the QNetworkAccessManager. 如果我们丢失了连接或连接超时,则将触发QNetworkAccessManager的finish finished()信号。 We try to reconnect to the event source (We connected this slot to the signal when we created our QNetworkAccessManager instance): 我们尝试重新连接到事件源(在创建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";
    }
}

You can find the demo here: https://github.com/DylanVanAssche/Qt-Server-Sent-Events-Demo 您可以在此处找到演示: https : //github.com/DylanVanAssche/Qt-Server-Sent-Events-Demo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM