• 【WebSocket】Qt客户端


    如果还不了解 WebSocket,可以参考我的上一篇博客:【WebSocket】入门教程(JS)

    Qt 提供的 QWebSocket 既可以用于客户端应用程序,也可以用于服务端应用程序,接口大部分和 QTcpSocket 一致。

    QWebSocket 当前不支持 WebSocket 扩展和 WebSocket 子协议,仅支持 WebSocket 协议的版本13 (如 RFC 6455 中所述)。


    一、WebSocket测试网站

    上面是本人搜索到的可以用于 WebSocket 测试的工具网站,用于测试下面写的 WebSocketClinet。


    二、效果展示

    效果图如下所示:

    WebSocket_Qt_A.png


    三、代码实现

    准备工作

    创建 Qt Widget 工程,首先需要在 .pro 文件中引入:

    QT += websockets
    

    WebSocketClinet.h

    #ifndef WEBSOCKETCLIENT_H
    #define WIDGET_H
    
    #include <QObject>
    #include <QtWebSockets>
    #include <QDebug>
    #include <QUrl>
    
    // WebSocket客户端管理类
    class WebSocketClinet : public QObject
    {
        Q_OBJECT
    
    public:
        explicit WebSocketClinet(QObject *parent = 0);
        ~WebSocketClinet();
    
        void connectUrl(QString url); // 连接websocket服务器的URL
        void close(); // 关闭websocket
        void sendTextMsg(const QString &message); // 发送Text类型的消息
        void sendBinaryMsg(const QByteArray &data); // 发送Binary类型的消息
        bool getConStatus(); // 返回服务器连接状态
    
    signals:
        void sigRecvTextMsg(QString message); // 接受到Text类型消息的信号
    
    private slots:
        void slotConnected(); // 连接成功
        void slotDisconnected(); // 断开连接
        void slotRecvTextMsg(QString message); // 接受字符数据
        void slotRecvBinaryMsg(QByteArray message); // 接受二进制数据
        void slotError(QAbstractSocket::SocketError error); // 响应报错
    
    private:
        void reconnect(); // 断开重连
    
        QWebSocket  *m_pWebSocket;
        QUrl m_url;
        bool m_bConnected = false; // 为true,表明已连接服务器,否则未连接上
    };
    
    #endif // WEBSOCKETCLIENT_H
    

    WebSocketClinet.cpp

    #include "WebSocketClinet.h"
    
    WebSocketClinet::WebSocketClinet(QObject *parent)
        : QObject(parent)
    {
        m_pWebSocket = new QWebSocket();
    
         // 连接相应的信号槽
        connect(m_pWebSocket, SIGNAL(connected()), this, SLOT(slotConnected()));
        connect(m_pWebSocket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
        connect(m_pWebSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotError(QAbstractSocket::SocketError)));
    }
    
    WebSocketClinet::~WebSocketClinet()
    {
        if(m_pWebSocket != 0)
        {
            m_pWebSocket->deleteLater();
            m_pWebSocket = 0;
        }
    }
    
    // 连接websocket服务器的URL
    void WebSocketClinet::connectUrl(QString url)
    {
        m_url = QUrl(url);
        m_pWebSocket->open(m_url);
    }
    
    // 关闭websocket
    void WebSocketClinet::close()
    {
        m_pWebSocket->close();
    }
    
    // 发送Text类型的消息
    void WebSocketClinet::sendTextMsg(const QString &message)
    {
        if(!m_bConnected)
        {
            qDebug() << __FILE__ << __LINE__ << "Failed to" << __FUNCTION__ << ", it's not running...";
            return;
        }
        //qDebug() << "send: " << message;
        m_pWebSocket->sendTextMessage(message);
    }
    
    // 发送Binary类型的消息
    void WebSocketClinet::sendBinaryMsg(const QByteArray &data)
    {
        if(!m_bConnected)
        {
            qDebug() << __FILE__ << __LINE__ << "Failed to" << __FUNCTION__ << ", it's not running...";
            return;
        }
        m_pWebSocket->sendBinaryMessage(data);
    }
    
    // 返回服务器连接状态
    bool WebSocketClinet::getConStatus()
    {
        return m_bConnected;
    }
    
    // 连接成功
    void WebSocketClinet::slotConnected()
    {
        qDebug()<<"connect successful";
        m_bConnected = true;
    
        connect(m_pWebSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(slotRecvTextMsg(QString)));
        connect(m_pWebSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(slotRecvBinaryMsg(QByteArray)));
    }
    
    // 断开连接
    void WebSocketClinet::slotDisconnected()
    {
        qDebug() << __FILE__ << __LINE__ << "disconnected";
        reconnect();
    }
    
    // 接受字符数据
    void WebSocketClinet::slotRecvTextMsg(QString message)
    {
        emit sigRecvTextMsg(message);
    }
    
    // 接受二进制数据
    void WebSocketClinet::slotRecvBinaryMsg(QByteArray message)
    {
        qDebug() << "slotRecvBinaryMsg: " << message;
    }
    
    // 响应报错
    void WebSocketClinet::slotError(QAbstractSocket::SocketError error)
    {
        qDebug() << __FILE__ << __LINE__ << (int)error << m_pWebSocket->errorString();
    }
    
    // 断开重连
    void WebSocketClinet::reconnect()
    {
       qDebug() << "websocket reconnected";
       m_pWebSocket->abort();
       m_pWebSocket->open(m_url);
    }
    

    Widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QListWidget>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QHBoxLayout>
    #include <QVBoxLayout>
    #include <QMessageBox>
    #include "WebSocketClinet.h"
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = nullptr);
        ~Widget();
    
    private slots:
        void slotSendMsg(); // 发送消息的槽函数
        void slotRecvTextMsg(QString sMessage); // 接受WebSocketClient传来的文本消息
    
    private:
        QListWidget *listwidget;
        QLineEdit *lineedit;
    
        WebSocketClinet *m_pWebSocketClinet; // WebSocket客户端
    };
    
    #endif // WIDGET_H
    

    Widget.cpp

    #include "widget.h"
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent)
    {
        this->setWindowTitle("WebSocket客户端");
    
        // 初始化窗口部件
        listwidget = new QListWidget;
        lineedit = new QLineEdit;
        QPushButton *sendbutton = new QPushButton("发  送");
        QPushButton *cancelbutton = new QPushButton("取  消");
        this->connect(sendbutton, SIGNAL(clicked()), this, SLOT(slotSendMsg()));
        this->connect(cancelbutton, SIGNAL(clicked()), this,SLOT(close()));
    
        // 布局
        QHBoxLayout * hlayout = new QHBoxLayout;
        hlayout->addStretch(0);
        hlayout->addWidget(sendbutton);
        hlayout->addWidget(cancelbutton);
        QVBoxLayout *vlayout = new QVBoxLayout(this);
        vlayout->addWidget(listwidget);
        vlayout->addWidget(lineedit);
        vlayout->addLayout(hlayout);
    
        // 初始化服务器
        m_pWebSocketClinet = new WebSocketClinet;
        m_pWebSocketClinet->connectUrl("ws://49.234.18.41:8866");
        connect(m_pWebSocketClinet, SIGNAL(sigRecvTextMsg(QString)), this, SLOT(slotRecvTextMsg(QString)));
    }
    
    Widget::~Widget()
    {
    
    }
    
    // 发送消息的槽函数
    void Widget::slotSendMsg()
    {
        QString content = lineedit->text(); //获取单行文本框内要发送的内容
        if(!content.isEmpty())
        {
            QDateTime datetime = QDateTime::currentDateTime();
            QString str = "send to server : " + datetime.toString("yyyy-M-dd hh:mm:ss") + tr("
    ");
            str += content;
            listwidget->addItem(str);   // 将要发送的内容显示在listwidget
            m_pWebSocketClinet->sendTextMsg(str); // 发送消息到服务器
        }
        else
        {
            QMessageBox::critical(this, "错误", "不能发送空消息!", QMessageBox::Ok);
        }
        lineedit->clear();
    }
    
    // 接受WebSocketClient传来的文本消息
    void Widget::slotRecvTextMsg(QString sMessage)
    {
        // 加上时间帧
        QDateTime datetime = QDateTime::currentDateTime();
        QString str = tr("recv from server : ") + datetime.toString("yyyy-M-dd hh:mm:ss") + tr("
    ");
        str += sMessage;
    
        listwidget->addItem(str);   // 将接收到的内容加入到listwidget
    }
    

    参考:

    Qt开发技术:QWebSocket客户端、服务端介绍与开发


  • 相关阅读:
    Average Score39届亚洲赛牡丹江站A题
    Average Score39届亚洲赛牡丹江站A题
    Building Fire Stations 39届亚洲赛牡丹江站B题
    Leetcode 155 Min Stack 小顶堆+栈,优先队列实现 难度:0
    pycharm 使用小结
    POJ 3020 Antenna Placement 匈牙利算法,最大流解法 难度:1
    POJ 3041 Asteroids 匈牙利算法,最大流解法,行列为点 难度:1
    POJ 1094 Sorting It All Out 拓扑排序 难度:0
    POJ 2240 && ZOJ 1082 Arbitrage 最短路,c++ stl pass g++ tle 难度:0
    POJ 1125 Stockbroker Grapevine 最短路 难度:0
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/14527821.html
Copyright © 2020-2023  润新知