Qt WebSocket的基本使用

(只是作为个人纪录,如果你要使用的话在 Qt 示例里搜 websocket 看官方 Demo 就行了,代码量不多)

0.前言

(参见Qt文档说明)WebSockets 是一种通过单个 TCP 连接提供全双工通信信道的 web 技术。2011年,IETF 将 WebSocket 协议标准化为 RFC 6455 。Qt 提供的 QWebSocket 既可以用于客户端应用程序,也可以用于服务端应用程序,接口大部分和 QTcpSocket 一致。

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

1.QWebSocket与QWebSocketServer的基本使用

(完整代码链接,包含 Qt Server/Client 和 HTML Client:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/QtWebSocketDemo)

要使用 Qt 的 WebSocket 模块,先在 pro 文件中加上 websockets:

QT += websockets

这是我 Demo 界面:

Qt WebSocket的基本使用_第1张图片

对于服务端,需要用到 QWebSocketServer 和 QWebSocket 两个类。创建 Server 对象后,使用 listen 函数监听端口,新的连接到来时,触发 newConnection 信号,这时候才槽函数种使用 nextPendingConnection 函数获取到这个 Socket 连接。

主要实现代码:

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

    //构造:QWebSocketServer(const QString& serverName,QWebSocketServer::SslMode secureMode,QObject *parent=nullptr)
    //使用给定的serverName构造一个新的QWebSocketServer。
    //该服务器名称将在HTTP握手阶段被用来识别服务器。它可以为空,此时不会将服务器名称发送给客户端。
    //SslMode指示服务器是通过wss(SecureMode)还是ws(NonSecureMode)运行
    //QWebSocketServer::SecureMode服务器以安全模式运行(通过wss)
    //QWebSocketServer::NonSecureMode服务器以非安全模式运行(通过ws)
    server=new QWebSocketServer("Server",QWebSocketServer::NonSecureMode,this);

    //服务器监听
    ui->btnSend->setEnabled(false);
    connect(ui->btnListen,&QPushButton::clicked,[this](){
        if(ui->btnListen->text()!="Listen"){
            ui->btnSend->setEnabled(false);
            ui->btnListen->setText("Listen");
            clearClient();
            server->close();
        }else{
            QHostAddress address;
            if(ui->editAddress->text()=="Any"){
                address=QHostAddress::Any;
            }else{
                address=QHostAddress(ui->editAddress->text());
            }
            //判断是否连接上
            if(server->listen(address,ui->editPort->text().toUInt())){
                ui->btnSend->setEnabled(true);
                ui->btnListen->setText("Dislisten");
            }
        }
    });
    //新的连接进来
    connect(server,&QWebSocketServer::newConnection,this,&WebSocketServer::onNewConnection);
    //发送消息给客户端
    connect(ui->btnSend,&QPushButton::clicked,[this](){
        if(!ui->editSend->toPlainText().isEmpty())
            emit sendMessage(ui->editSend->toPlainText());
    });
}

WebSocketServer::~WebSocketServer()
{
    clearClient();
    server->close();
    delete ui;
}

void WebSocketServer::clearClient()
{
    for(int i=clientList.count()-1;i>=0;i--)
    {
        //qDebug()<disconnect();
        clientList.at(i)->close();
    }
    qDeleteAll(clientList);
    clientList.clear();
}

void WebSocketServer::onNewConnection()
{
    QWebSocket *socket=server->nextPendingConnection();
    if(!socket)
        return;
    clientList.push_back(socket);
    ui->editRecv->append(QString("[New Connect] Address:%1  Port:%2")
                         .arg(socket->peerAddress().toString())
                         .arg(socket->peerPort()));

    //收到消息
    connect(socket,&QWebSocket::textMessageReceived,[this](const QString &msg){
        ui->editRecv->append(msg);
    });
    //发送消息
    connect(this,&WebSocketServer::sendMessage,socket,&QWebSocket::sendTextMessage);
    //断开连接,释放
    connect(socket,&QWebSocket::disconnected,[this,socket](){
        clientList.removeAll(socket);
        socket->deleteLater();
    });
}

 对于客户端,好像没有指定 bind 自己端口的接口,只能指定服务端的 Url。通过 open 函数连接服务端的 Url ,使用 close 关闭连接。数据到来的时候有 textMessageReceived 和 binaryMessageReceived 等信号触发,也可以调用 sendTextMessage 或 sendBinaryMessage 发送数据。

主要实现代码:

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

    //构造:QWebSocket(const QString &origin = QString(), QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest, QObject *parent = nullptr)
    //使用给定的源,要使用的协议版本和parent创建一个新的QWebSocket 。
    client=new QWebSocket;
    client->setParent(this);

    //连接服务端
    connect(ui->btnOpen,&QPushButton::clicked,[this](){
        if(ui->btnOpen->text()!="Open"){
            client->close();
        }else{
            client->open(QUrl(ui->editUrl->text()));
        }
    });
    //连接结果
    ui->btnSend->setEnabled(false);
    connect(client,&QWebSocket::connected,[this](){
        ui->btnSend->setEnabled(true);
        ui->btnOpen->setText("Close");
        ui->footLabel->setText(QString("Address:%1  Port:%2")
                               .arg(client->localAddress().toString())
                               .arg(client->localPort()));
        qDebug()<<"connected";
    });
    connect(client,&QWebSocket::disconnected,[this](){
        ui->btnSend->setEnabled(false);
        ui->btnOpen->setText("Open");
        qDebug()<<"disconnected";
    });
    //发送数据
    connect(ui->btnSend,&QPushButton::clicked,[this](){
        if(!ui->editSend->toPlainText().isEmpty())
            client->sendTextMessage(ui->editSend->toPlainText());
    });
    //接收数据
    connect(client,&QWebSocket::textMessageReceived,[this](const QString &msg){
        ui->editRecv->append(msg);
    });
}

WebSocketClient::~WebSocketClient()
{
    //结束的时候没关会异常
    client->close();
    delete ui;
}

网页 WebSocket 客户端的简单 Demo: 





    
    
    Qt WebSocket Demo



    
    
    

Recv:



Send:



2.使用带SSL的WebSocket(略,暂时没用到)

3.提示[LspTrace]ReadAccConfig returns false!

Qt WebSocket的基本使用_第2张图片

Windows 命令行(管理员权限)输入 netsh winsock reset,等出现提示后重启电脑。

参考:https://blog.csdn.net/zxl_1996/article/details/86333945

Netsh winsock reset是一个命令提示程序,用于将winsock目录重置为默认设置或清除状态。如有时候上不了网或者网络出现问题经常用到它,简单地理解就是:重置程序通过操作系统链接网络的入口点。虽然使用此命令可以恢复网络连接,也应谨慎使用,因为可能需要重新安装LSPLSP: layered service privider 分层服务提供商。LSP是TCP/IP等协议的接口。

参考:https://baijiahao.baidu.com/s?id=1621092219410327325&wfr=spider&for=pc

4.参考

Qt 文档:https://doc.qt.io/qt-5/qwebsocket.html

HTML Websocket:https://www.runoob.com/html/html5-websocket.html

你可能感兴趣的:(Qt,略知一二)