使用Node.js和Socket.io监听Qt桌面端口

4
我使用Qt构建了一个桌面应用程序。目前,该应用程序定期从远程Web服务器上的XML文件中提取数据以填充应用程序中的各种小部件。
与其拉取数据,我宁愿实现一个“推送”环境,其中Qt应用程序在远程Web服务器上的端口上建立持久连接,并侦听来自node.js的更新或“广播”。
我已经使用node.js和socket.io构建了类似于基于Web的应用程序,所以我对此并不陌生,但我似乎无法弄清楚如何在Qt中完成这项工作。我可以使用QTcpSocket连接到4000端口,并使用node.js启动HTTP服务器,但我似乎无法接收到任何广播消息。
这里缺少的一块是socket.io,但我不知道如何在Qt内使用它或建立所需的连接 - 所以我很困惑。
在Qt应用程序内连接并侦听4000端口。
void MainWindow::connectTcp() {

client = new QTcpSocket(this);
QHostAddress hostadd("myIPaddress");
connect(client,SIGNAL(connected()),this,SLOT(isConnected()));
    connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(connectionError(QAbstractSocket::SocketError)));
connect(client, SIGNAL(readyRead()), this, SLOT(readTcpData()));
client->connectToHost(hostadd,3000);

} 

在node.js中创建服务器并发送更新

var http = require('http'); 
var url = require('url');
var msg = '';

var port = 4000;
/* path to socket.io */
var path = '/path/to/node_modules/socket.io';

var server = http.createServer(function (req, res) {

        req.on('data', function (d) {
            data += d;
        });
        req.on('end',function(){
            msg = data;
    res.writeHead(200,{'Content-Type':'text/plain'});
    res.write(msg);
    res.end();
    console.log('SEND DATA: ',msg);
        });

}).listen(port);

非常感谢您的建议 - 我正在尝试做的事情是否可能?

编辑 - 更新

在尝试使用C ++集成Socket.io和WebSocket失败后,我尝试使用QWebView并成功了。 我将下面我所做的细节分享出来,以防其他人需要帮助。

mainwindow.cpp

这只是一个通用的Qt Gui应用程序,其唯一目的是创建一个加载HTML文件的QWebView实例。正在加载(后台中)的HTML文件包含建立套接字连接的javascript代码。
我创建了一个单独的Qt类来与index.html中的javascript进行接口,以便对服务器响应作出反应。更多信息
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Set default proxy (this may not always be necessary)
    QNetworkProxyFactory::setUseSystemConfiguration(true);

    h = new Hello(this);

    view = new QWebView(this);
    view->load(QUrl("http://www.mydomain.com/startconnection.html"));

    // I don't want the webview to show, it should run in the background
    view->hide(); 

    frame = view->page()->mainFrame();
    connect(view,SIGNAL(loadFinished(bool)),this,SLOT(loadFinished(bool)));

}

void MainWindow::loadFinished(bool loaded) {

    qDebug() << "Webpage Loaded? " << loaded;

}


MainWindow::~MainWindow()
{
    delete ui;
}

http://www.mydomain.com/startconnection.html

这是加载到Qt中的页面。它只是简单地建立Socket.io连接到监听4000端口的mydomain.com。
<html>
<head>
<script type="text/javascript" src="http://www.mydomain.com:4000/socket.io/socket.io.js"></script> 
<script type="text/javascript">

var socket;

window.onload = onLoad;

function onLoad() {

    socket = io.connect('http://www.mydomain.com:4000');

    socket.on('connect', function(){
        alert("Connected To Socket");
    });

    socket.on('message',function(data) {
        alert("Here Comes A Message From The Server");
    });

}

</script>
</head>
<body>
</body>
</html>

/var/www/vhosts/mydomain.com/socket/server.js

这是启动HTTP服务并监听4000端口连接的节点脚本。我使用“forever”启动了该服务,并将所有console.info消息输出到日志文件中,命令如下:forever -al /var/www/vhosts/mydomain.com/connection.log start /var/www/vhosts/mydomain.dom/socket/server.js。
var http = require('http'); 
var url = require('url');
var qs = require('querystring');
var child_process = require('child_process');
var theSockets = {};

/* listening port */
var port = 4000;
/* path to socket.io on server */
var path = '/var/www/vhosts/mydomain.com/httpdocs/server/node_modules/socket.io';

var server = http.createServer(function (req, res) {

         var data = '';
         var msg = '';

        req.on('data', function (d) {
                data += d;
        });

        req.on('end',function(){
            msg = data;
            io.sockets.emit('message',msg);
            res.end();
        });

        }

        res.end();

}).listen(port);

var io = require(path).listen(server);

io.sockets.on('connection', function(socket) {

    var d = new Date();
    console.log('JOINED SOCKET '+d.toLocaleString()+' SOCKET ID '+socket.id);

    socket.on('disconnect',function() {

    var d = new Date();
    console.log('EXITED SOCKET '+d.toLocaleString()+' SOCKET ID '+socket.id);

    });

});

希望这能帮助到某个人!

Qt上的socket.io服务器回调函数类,GITHUB链接:https://github.com/ChadyG/QtSocketIOServer - 3P5iL0WNE
2个回答

2

是的,这是可能的,但你必须了解Socket.IO处理WebSocket套接字而不是原始TCP。你的客户端应该与服务器进行WebSocket握手等操作。目前的情况是,在客户端上创建一个“HTTP”连接,不发送任何内容并等待某种事件发生(什么也不会发生)。

当然,您还可以设计一种协议来运行在原始TCP上,例如发送以换行符/空值分隔(或netstring封装)的JSON块。


谢谢。我在Google上搜索到了这个Github链接,其中有一个用于C++编写的Socket.io版本。需要Boost和其他依赖项。我会尝试一下,如果成功了就回复您。 - Marc
没有成功。我按照Boost.org网站和这里的说明安装了C++的Boost库,然后我安装了rapidjson。我安装了Socket.io和WebSockets。但是我遇到了很多错误——这让我相信这个解决方案只适用于Microsoft Visual C++,而不适用于Qt。 - Marc

1
你可以查看QWebSockets,它使用Qt实现了websockets。我还构建了客户端和服务器socket.io类,很快将开源发布。
编辑: 在这里here找到它。

很高兴能看到你的实现,做得很棒! - Checo R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接