从QWebSocketServer实时向客户端发送一系列消息



我在QCoreApplication中实现了一个websocket服务器。一旦与客户端建立了连接,我希望立即实时向其发送一系列消息,消息之间的延迟为0.5秒。但是,只有在发送完所有消息之后,或者在下面的websocket服务器实现中sendMyMessages()方法返回之后,单个消息才能到达客户端。如果我有大量的消息要发送,客户端必须等待很长时间才能一次性获得所有消息。

MyWebSocketServer.h

#ifndef MYWEBSOCKETSERVER_H
#define MYWEBSOCKETSERVER_H
#include <QtCore/QObject>
#include <QtCore/QList>
#include <QtCore/QByteArray>
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
class MyWebSocketServer : public QObject
{
Q_OBJECT
public:
explicit MyWebSocketServer(quint16 port,
bool debug = false,
QObject *parent = nullptr);
~MyWebSocketServer();
Q_SIGNALS:
void closed();
private Q_SLOTS:
void onNewConnection();
void socketDisconnected();
private:
void sendMyMessages(QWebSocket *client);
QWebSocketServer *m_pWebSocketServer;
QList<QWebSocket *> m_clients;
bool m_debug;
};
#endif // MYWEBSOCKETSERVER_H

MyWebSocketServer.cpp

#include "MyWebSocketServer.h"
#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <QtWebSockets/qwebsocketserver.h>
#include <QtWebSockets/qwebsocket.h>
#include <QtCore/QDebug>
QT_USE_NAMESPACE

MyWebSocketServer::MyWebSocketServer(quint16 port,
bool debug,
QObject *parent)
: QObject(parent)
, m_pWebSocketServer(new QWebSocketServer(
QStringLiteral("My WebSocket Server"),
QWebSocketServer::NonSecureMode,
this))
, m_debug(debug)
{
connect(m_pWebSocketServer,
&QWebSocketServer::newConnection,
this,
&MyWebSocketServer::onNewConnection);
connect(m_pWebSocketServer,
&QWebSocketServer::closed,
this,
&MyWebSocketServer::closed);
m_pWebSocketServer->listen(QHostAddress::LocalHost, port);
}
MyWebSocketServer::~MyWebSocketServer()
{
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
void MyWebSocketServer::onNewConnection()
{
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket,
&QWebSocket::disconnected,
this,
&MyWebSocketServer::socketDisconnected);
m_clients << pSocket;
sendMyMessages(pSocket);
}
void MyWebSocketServer::sendMyMessages(QWebSocket *client)
{
std::fstream jsonStringFileHandler;
jsonStringFileHandler.open("my-messages.txt", std::ios::in);
if (jsonStringFileHandler.is_open())
{
std::string message;
while(getline(jsonStringFileHandler, message))
{
// Individual messages don't go through immediately
// Only after this method returns, all the messages show up on the client's end
// Is it possible to send the individual messages immediately? (probably with a 0.5 second delay)
client->sendTextMessage(QString::fromUtf8(message.c_str()));
}
jsonStringFileHandler.close();
}
}
void MyWebSocketServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (pClient)
{
m_clients.removeAll(pClient);
pClient->deleteLater();
}
}

只有在sendMyMessages()返回之后,客户端才能获得所有消息。它不是实时的。我知道在使用一些异步编程技术后可以实现我现在的状态,但我无法找到在我的websocket服务器实现中设置它的方法。

以下是我使用websocketsasyncio模块在Python中使用的websocket服务器的实现。然而,我希望使用Qt在C++中实现相同的逻辑。

import asyncio
import websockets
async def sendMyMessages(websocket, path):
with open("my-messages.txt") as fp:
lines = fp.readlines()
for line in lines:
await asyncio.sleep(0.5)
await websocket.send(line.strip())
start_server = websockets.serve(sendMyMessages, "127.0.0.1", 3000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

我发现的一种方法在调用QWebSocket::sendTextMessage()后立即使用QWebSocket::flush()

来自QWebSocket::flush()、上的文档

此函数在不阻塞的情况下,尽可能多地从内部写入缓冲区写入底层网络套接字。如果写入了任何数据,此函数将返回true;否则返回false。如果您需要QWebSocket立即开始发送缓冲数据,请调用此函数。成功写入的字节数取决于操作系统。在大多数情况下,您不需要调用此函数,因为一旦控件返回到事件循环,QWebSocket将自动开始发送数据。

但是,我不确定这是否是正确的方法,因为文档表明数据可能无法可靠地写入底层网络套接字。如果有更好的技术,我会很高兴知道的!

client->sendTextMessage(QString::fromUtf8(message.c_str()));
client->flush();
std::this_thread::sleep_for(std::chrono::milliseconds(50));

最新更新