zoukankan      html  css  js  c++  java
  • Qt开源作品37-网络中转服务器

    一、前言

    用Qt做开发10年了,其中做过好多项目,基于现在web和移动互联网发展如此迅猛,大量的应用场景需要一个网络中转服务器,可以实现手机app或者其他客户端远程回控设备,现在物联网发展非常迅猛,这个将来也是大势所趋,所以有这个想法很久了,打算用Qt也来做个简单的网络中转服务器。

    需求场景:

    1. 手机端或者其他端可以对设备进行回控,并查看设备各种运行状态,接收报警推送等。
    2. 同时支持在局域网、广域网、互联网访问,尤其是互联网访问。
    3. 权限控制,给定账号控制授权的设备,并自动拉取设备信息。
    4. 设备不在线要给出反馈信息提示以便分析。
    5. 每个连接都有自己的唯一编号作为标识符。
    6. 可以方便的拓展为微信接入+小程序接入+web接入。

    二、代码思路

    #include "tcpserver1.h"
    #include "quiwidget.h"
    
    TcpClient1::TcpClient1(QObject *parent) :  QTcpSocket(parent)
    {
        ip = "127.0.0.1";
        port = 6907;
        deviceID = "SSJC00000001";
    
        connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(deleteLater()));
        connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
        connect(this, SIGNAL(readyRead()), this, SLOT(readData()));
    }
    
    void TcpClient1::setIP(const QString &ip)
    {
        this->ip = ip;
    }
    
    QString TcpClient1::getIP() const
    {
        return this->ip;
    }
    
    void TcpClient1::setPort(int port)
    {
        this->port = port;
    }
    
    int TcpClient1::getPort() const
    {
        return this->port;
    }
    
    QString TcpClient1::getDeviceID()
    {
        return this->deviceID;
    }
    
    void TcpClient1::readData()
    {
        QByteArray data = this->readAll();
        if (data.length() <= 0) {
            return;
        }
    
        //取出唯一标识符,并过滤,可自行更改过滤条件
        QByteArray cmd = data.mid(App::CmdStart1, App::CmdLen1);
        QString id = QString(cmd);
        if (id.startsWith("S") && deviceID != id) {
            deviceID = id;
            //发送信号更新标识符
            emit receiveDeviceID(ip, port, deviceID);
        }
    
        QString buffer;
        if (App::HexData1) {
            buffer = QUIHelper::byteArrayToHexStr(data);
        } else {
            buffer = QString(data);
        }
    
        emit receiveData(ip, port, deviceID, buffer);
    }
    
    void TcpClient1::sendData(const QString &data)
    {
        QByteArray buffer;
        if (App::HexData1) {
            buffer = QUIHelper::hexStrToByteArray(data);
        } else {
            buffer = data.toLatin1();
        }
    
        this->write(buffer);
        emit sendData(ip, port, deviceID, data);
    }
    
    TcpServer1::TcpServer1(QObject *parent) : QTcpServer(parent)
    {
    }
    
    #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
    void TcpServer1::incomingConnection(qintptr handle)
    #else
    void TcpServer1::incomingConnection(int handle)
    #endif
    {
        TcpClient1 *client = new TcpClient1(this);
        client->setSocketDescriptor(handle);
        connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
        connect(client, SIGNAL(sendData(QString, int, QString, QString)), this, SIGNAL(sendData(QString, int, QString, QString)));
        connect(client, SIGNAL(receiveData(QString, int, QString, QString)), this, SIGNAL(receiveData(QString, int, QString, QString)));
        connect(client, SIGNAL(receiveDeviceID(QString, int, QString)), this, SIGNAL(receiveDeviceID(QString, int, QString)));
    
        QString ip = client->peerAddress().toString();
        int port = client->peerPort();
        QString deviceID = client->getDeviceID();
        client->setIP(ip);
        client->setPort(port);
        emit clientConnected(ip, port, deviceID);
        emit sendData(ip, port, deviceID, "客户端上线");
    
        //追加到链表中
        clients.append(client);
    }
    
    void TcpServer1::disconnected()
    {
        TcpClient1 *client = (TcpClient1 *)sender();
        QString ip = client->getIP();
        int port = client->getPort();
        QString deviceID = client->getDeviceID();
        emit clientDisconnected(ip, port, deviceID);
        emit sendData(ip, port, deviceID, "客户端下线");
    
        //断开连接后从链表中移除
        clients.removeOne(client);
    }
    
    bool TcpServer1::start()
    {
    #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
        bool ok = listen(QHostAddress::AnyIPv4, App::ListenPort1);
    #else
        bool ok = listen(QHostAddress::Any, App::ListenPort1);
    #endif
        return ok;
    }
    
    void TcpServer1::stop()
    {
        foreach (TcpClient1 *client, clients) {
            client->disconnectFromHost();
        }
    
        this->close();
    }
    
    bool TcpServer1::writeData(const QString &deviceID, const QString &data)
    {
        bool ok = false;
        foreach (TcpClient1 *client, clients) {
            if (client->getDeviceID() == deviceID) {
                client->sendData(data);            
                ok = true;            
            }
        }   
    
        return ok;
    }
    

    三、效果图

    四、开源主页

    以上作品完整源码下载都在开源主页,会持续不断更新作品数量和质量,欢迎各位关注。

    1. 国内站点:https://gitee.com/feiyangqingyun/QWidgetDemo
    2. 国际站点:https://github.com/feiyangqingyun/QWidgetDemo
    3. 个人主页:https://blog.csdn.net/feiyangqingyun
    4. 知乎主页:https://www.zhihu.com/people/feiyangqingyun/
  • 相关阅读:
    关于Ubuntu中passwd、shadow、group等文件
    Android colors.xml 颜色列表
    【设计】线框图、原型和视觉稿的区别
    【设计】24款线框图相关工具及资源大放送
    【辅助工具】20款优秀的移动产品原型和线框图设计工具(二)
    【辅助工具】20款优秀的移动产品原型和线框图设计工具(一)
    GET RESTful With Python
    VRRP、Track与NQA联动配置举例(Master监视上行链路)
    静态路由、Track与NQA联动配置举例
    ROS-MikroTik-RouterOS-培训认证各种证书
  • 原文地址:https://www.cnblogs.com/feiyangqingyun/p/13171633.html
Copyright © 2011-2022 走看看