基于websocket的简单通信

首次接触websocket通信协议,不足之处希望指出一起进步。

简述

websocket是基于tcp协议的一种网络通信协议,分为客户端和服务端,可以实现客户端与服务端的双向通信。
与tcp的不同之处是:
1.客户端与服务端只需要一次握手协议,就可以建立比较持久的网络连接;
2.客户端不需要向服务端发送连接请求。
服务端监听指定的端口之后,客户端只需打开服务端的url,就可建立连接。

简单的项目实例

  1. 项目简述
    在客户端与服务端建立连接的情况下,服务端向客户端发送json字符串,客户端接收到json字符串并显示,客户端一旦收到二进制消息,服务端接收来自客户端的文本消息,并向客户端发送文本消息。

  2. 项目运行效果图
    服务端运行效果:在这里插入图片描述
    客户端运行效果:
    在这里插入图片描述

  3. 项目源码
    客户端
    main.cpp

#include "dialog.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.createWebsocket();
    w.show();
    return a.exec();
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtWebSockets/QWebSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();

    void createWebsocket();

public slots:
    void slot_onConnected();
    void slot_onDisconnected();
    void slot_onTextMsgRecevied(const QString &msg);
    void slot_onBinaryMessageReceived(const QByteArray &message);
    void slot_onError(QAbstractSocket::SocketError error);

private:
    Ui::Dialog *ui;
    QWebSocket *m_client;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowTitle(tr("Client"));
}

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

void Dialog::createWebsocket()
{
    m_client = new QWebSocket();
    m_client->open(QUrl("ws://localhost:6666"));
    connect(m_client, &QWebSocket::connected, this, &Dialog::slot_onConnected);
    connect(m_client, &QWebSocket::disconnected, this, &Dialog::slot_onDisconnected);

    connect(m_client, &QWebSocket::binaryMessageReceived,this, &Dialog::slot_onBinaryMessageReceived);
    connect(m_client, &QWebSocket::textMessageReceived,this, &Dialog::slot_onTextMsgRecevied);
    connect(m_client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_onError(QAbstractSocket::SocketError)));
}

void Dialog::slot_onConnected()
{
//    connect(m_client, &QWebSocket::binaryMessageReceived,this, Dialog::slot_onTextMsgRecevied);
//    connect(m_client, &QWebSocket::textMessageReceived,this, Dialog::slot_onTextMsgRecevied);
    m_client->sendTextMessage(QStringLiteral("Hello,server!我连接你成功了"));
}

void Dialog::slot_onDisconnected()
{
    m_client->close();
    if(m_client != NULL)
    {
        delete m_client;
        m_client = NULL;
    }
}

void Dialog::slot_onTextMsgRecevied(const QString &msg)
{
    ui->plainTextEdit->appendPlainText(msg);
}

void Dialog::slot_onBinaryMessageReceived(const QByteArray &message)
{
    std::string strMsg = message.toStdString();
    //接收JSON字符串
    ui->plainTextEdit->appendPlainText(QString::fromStdString(strMsg));
}

void Dialog::slot_onError(QAbstractSocket::SocketError error)
{
    QTextStream(stdout)<<m_client->errorString();
}

ui文件
在这里插入图片描述
客户端项目结构
在这里插入图片描述
服务端
main.cpp

#include "dialog.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.createWebServer();
    w.show();
    return a.exec();
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();

    void createWebServer();
    QString getCurrFilePath(QString fileName);
    QByteArray readJsonConfigFile(QString &fileName);

public slots:
    void slot_onNewConnection();
    void slot_processMessage(const QString &msg);
    void slot_socketDisconnected();
    void slot_binaryMessageReceived(const QByteArray &message);
private:
    Ui::Dialog *ui;
    QWebSocketServer *m_serve;
    QWebSocket *      m_client;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include <QFile>

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowTitle(tr("Server"));
}

Dialog::~Dialog()
{
    if(m_serve != NULL)
    {
        m_serve->close();//设置了父窗口,就不用delete
    }

    delete ui;
}

void Dialog::createWebServer()
{
    m_serve = new QWebSocketServer("test1",QWebSocketServer::NonSecureMode,this);//非安全sw
    m_serve->listen(QHostAddress::LocalHost,6666);
    connect(m_serve, &QWebSocketServer::newConnection, this, &Dialog::slot_onNewConnection);
}

void Dialog::slot_onNewConnection()
{
    m_client = m_serve->nextPendingConnection();
    QString strFileName = getCurrFilePath("config2.json");
    QByteArray jsonArray = readJsonConfigFile(strFileName);
    m_client->sendBinaryMessage(jsonArray);
//    m_client->sendTextMessage("什么??客户端你好!");
    connect(m_client,&QWebSocket::binaryMessageReceived,this,&Dialog::slot_binaryMessageReceived);
    connect(m_client, &QWebSocket::textMessageReceived,this, &Dialog::slot_processMessage);
    connect(m_client, &QWebSocket::disconnected,this, &Dialog::slot_socketDisconnected);
}

void Dialog::slot_processMessage(const QString &msg)
{
 //   m_client->sendTextMessage("客户端,你收到消息了?");
    ui->textEdit->append(msg);
    m_client->sendTextMessage("客户端,我收到你的消息了");
}

void Dialog::slot_socketDisconnected()
{
    m_client->close();
}

void Dialog::slot_binaryMessageReceived(const QByteArray &message)
{
    ui->textEdit->append(QString::fromLocal8Bit(message));
}

QString Dialog::getCurrFilePath(QString fileName)
{
    QString strFileName =  QCoreApplication::applicationDirPath();//获取可执行文件的路径
    strFileName += "/" + fileName;
    return strFileName;
}

QByteArray Dialog::readJsonConfigFile(QString &fileName)
{
    QByteArray allData;
    qDebug()<<"文件路径及名称:"<<fileName;
   QFile file(fileName);
   if (!file.open(QIODevice::ReadOnly))
   {
       qDebug()<<"json配置文件读取失败!";
       return allData;
   }
   allData = file.readAll();
   file.close();
   qDebug()<<"json文件内容:"<<allData;
   return allData;
}

ui文件
在这里插入图片描述
服务端项目结构
在这里插入图片描述
5. 总结
websocket在通信的过程中服务端的步骤:
(1)创建QWebSocketServer对象或着指向QWebSocketServer的指针,创建时需指明服务器的名称,sslmode(即安全模式还是非安全模式,一般非SSL的情况下,采用的时非安全模式),另外还可以指明父窗口;
(2)监听IP和端口;
(3)绑定信号与槽函数,涉及到的常用信号与槽的绑定有:
@1 newConnection(),与客户端建立新的连接后触发这个信号;
@2 serverError(QWebSocketProtocol::CloseCode closeCode),服务器发生错误时触发该信号;
@3 可以在客户端建立连接后,服务端绑定客户端收到消息后的信号;
@4 可以在客户端建立连接后,服务端绑定客户端断开连接的信号;
(4)关闭服务端连接。
websocket在通信的过程中客户端的步骤:
(1)创建QWebSocket对象或着指向QWebSocket的指针;
(2)打开服务端的url;
(3)绑定信号与槽函数,常用的信号与槽函数的绑定如下:
@1 connected(),与服务端连接建立之后,信号被触发;
@2 disconnected(),与服务端连接断开之后,信号被触发;
@3 textMessageReceived(const QString &message),有文本消息到来的时候,信号被触发;
@4 binaryMessageReceived(const QByteArray &message),有二进制消息到来的时候,信号被触发;
@5 error(QAbstractSocket::SocketError error),发生错误的时候信号被触发;
6. 注意事项
(1).pro文件中添加QT += websockets,需加头文件#include <QtWebSockets/QWebSocket>和#include <QtWebSockets/QWebSocketServer>。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肩上风骋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值