我已经使用QTcpServer等编写了一个小型web服务器。它运行良好,所以我想进一步实现Qt的WebSocket功能。我希望WebSocket服务器可以在与我的web服务器相同的端口上访问(由于我的客户端网络的限制)。
我的WebSocket服务器应该可以在/admin/socket
访问,因此我需要一种方法将QTcpSocket(可以从/admin/socket
的请求处理程序访问)"升级"为QWebSocket。QWebSocket在该构造函数中具有此功能,该构造函数由QWebSocketServerPrivate中的此升级方法使用,但它都是私有的,仅由QWebocketServer内部使用。
有没有办法实现我上面所描述的?我必须实现我自己的WebSocket处理程序吗?
您需要将必要的文件从Qt的源复制到您的项目中,将QWebSocket
封装到命名空间中,这样它就不会与Qt自己的命名空间冲突,并使构造函数成为非私有的。这是实现这一点的唯一方法,无需编写大量自己的代码,也无需调用未定义的行为。
要使用您的类型,请通过using
使其可见;它将隐藏Qt的::QObject
,然后:
#include <QtCore>
namespace Foo { class QObject {}; }
int main() {
using Foo::QObject;
// ours vvvvvvv Qt's vvvvvvv
Q_ASSERT(sizeof(QObject) < sizeof(::QObject));
}
Qt附带源代码是有原因的:你应该在它有意义的时候使用它!
实际上,您也可以将QWebSocketServer
与自己的web服务器一起使用。您不应该使用此QWebSocketServer
的listen
,因为您自己的服务器已经在侦听某个端口。相反,您只需调用此QWebSocketServer
实例的handleConnection
,并从某个请求传递QTcpSocket
,而不是让自己的服务器处理请求。
问题是QWebSocketServer::handleConnection
期望没有从QTcpSocket
读取任何数据来访问TCP请求方法、URL和标头。但是,由于您不想将所有套接字传递给QWebSocketServer
,因此您需要peek
来自QTcpSocket
的数据,并通过搜索Upgrade: websocket
(不区分大小写)或检查URL来做出决定(由您自己的服务器处理或由QWebSocketServer
处理)。然后,您可以将QTcpSocket
传递给QWebSocketServer
实例,也可以为正常的HTTP响应执行自己的处理程序。如果您已经使用peek
完全读取了HTTP标头,那么在后一种情况下,您可以简单地在套接字上调用skip
。