美文网首页
Qt tcp编程

Qt tcp编程

作者: 随你说 | 来源:发表于2019-07-08 15:00 被阅读0次

    注意:网络编程需要在pro文件里添加 network,如该用到qSqldatabase 需要添加sql

    例:

    QT+= network\

        sql

    #一、QTcpsocket:

    QTcpsocet 是QT提供的tcp/ip的四层socket类.TCP(传输控制协议)是一种可靠的,面向流的,面向连接的传输协议。它特别适用于连续传输数据。

    QTcpsocket 是QAbstractSocket的子类.

    方法:

    QTcpsocet::connectToHost(str 'ip', int port, QIODevice::ReadWrite) //连接socket

     QTcpsocket::write(QBytearry) //数据的写入

    虚构函数:

    void QTcpsocket::readyRead() //实现接收到数据时执行

    二、QTcpServer: socket _server

    例子: 

    头文件

    ```

    #ifndef TCP_SERVER_H

    #define TCP_SERVER_H

    #include <QTcpServer>

    #include <QTcpSocket>

    #include <QJsonObject>

    #include <QObject>

    class tcp_server : public QTcpServer //重写QTcpServer

    {

        Q_OBJECT

    public:

        tcp_server(); //构造函数

        QByteArray data_length_data(QByteArray data);  //用于对要发送的数据头部添加包长度。

    protected:

        void incomingConnection(qintptr soketnember); //有新连接时执行,创造socket连接。

    signals:

    public slots:

       // void socket_write(QJsonObject user_passwd,QTcpSocket *tcpsocket);

    };

    class tcp_socket : public QTcpSocket  //重写tcpsocket

    {

        Q_OBJECT

    public:

        tcp_socket(qintptr soketDescriptor, QTcpSocket *parent=NULL); // soketDescriptor socket号。 

        void router(); //接收数据路由。

        QByteArray data_length_data(QByteArray data); //对发送的数据添加包长度

    private:

        int m_tcpBlockSize = 0;        //数据包长度计算

        bool is_one;                    //是否是第一个数据包

        int data_length;            //数据包长度

        QByteArray read_data;    //数据包缓存(在接收到的数据包未达到第一个包描述的大小时缓存用)

        //sql db;

    signals:

            void return_db(QJsonObject user_passwd,QTcpSocket *tcpsocket); //查询数据库信号,qsqldatabase 的多线程问题,所有发送信号到主进程。

    private slots:

        void Read_data(); //有数据进来时调用

    };

    #endif // TCP_SERVER_H

    '''

    .cpp部分:

    #include "tcp_server.h"

    #include <QTcpServer>

    #include <QThread>

    #include <QDebug>

    #include <QString>

    #include <QDataStream>

    #include <QJsonObject>

    #include <QJsonArray>

    #include <QByteArray>

    #include <QJsonDocument>

    //#include <QJsonObject>

    #include "sql.h"  //数据库查询,写入部分,于本笔记无关可忽略

    #include "cache.h" //全局变量,用于缓存最后一次的值,于本笔记无关,可忽略

    tcp_server::tcp_server()

    {

    }

    void tcp_server::incomingConnection(qintptr soketnember){ //有新连接时执行

        tcp_socket * socket=new tcp_socket(soketnember); //创建一个socket连接指针并按“本机套接字描述符”创建

        QThread *task=new QThread(); 创建一个线程地址。

        connect(socket,SIGNAL(disconnected()),task,SLOT(quit()));  //socket断开连接时退出线程

        connect(socket,SIGNAL(readyRead()),socket,SLOT(Read_data())); //有数据传入时执行Read_data()槽

        connect(socket,SIGNAL(return_db(QJsonObject,QTcpSocket*)),this,SLOT(socket_write(QJsonObject,QTcpSocket*))); //用于解决QSqldatabase 多线程问题,在需要查询数据库时发送给主进程执行,由主进程直接返回给客户端的socket 。

        socket->moveToThread(task); //移动socket 到线程

        task->start(); //线程启动

    }

    void tcp_server::socket_write(QJsonObject user_password,QTcpSocket *tcpsocket){

        sql db; //初始化数据库类,此类为自定义类,与本笔记无关

        qDebug()<<user_password;

        QString user=user_password.value("user").toString();

        QString password=user_password.value("password").toString();

        QJsonObject login_status=db.login(user,password);

        QJsonObject data_send;

        data_send.insert("type","login");

        data_send.insert("data",login_status);

        tcpsocket->write(data_length_data(QJsonDocument(data_send).toJson())); //socket 直接返回给客户端

        tcpsocket->waitForBytesWritten(1000); //写超时设定为1秒。

    }

    tcp_socket::tcp_socket(qintptr soketDescriptor, QTcpSocket *parent) :QTcpSocket(parent)

    {

        this->setSocketDescriptor(soketDescriptor); //设置这个连接的描述符是由QTcpserver传入的连接描述符。

    }

    void tcp_socket::Read_data(){  //读取数据

        if(m_tcpBlockSize==0){ //判断已接收的数据是否为0,0表示第一个数据包。

          QByteArray dd=this->readAll(); //读出所有数据。

          QDataStream cc(&dd,QIODevice::ReadWrite); //以流数据方式打开

          cc.device()->seek(0); //设置数据指针为0.

          cc>>data_length; //获取数据包大小。所以要求客户段传来的数据包前4个byte时int的包大小。

          if(!data_length>8){

              this->disconnect();

              this->close();

          }

    // 包描述: qbytearry [int(包大小),xxxxxxxxxxxxxxxxxxxxxxx.......数据部分]

          cc.device()->seek(sizeof(int)); //移动指针到包大小描述后的数据开始位。

            while (!cc.atEnd()) { //循环判断数据是否读取到结尾

                unsigned char tmp_char;

                cc>>tmp_char;

                read_data.append(tmp_char); //把每个byte追加到缓存中。

            }

    //        qDebug()<<data_length<<read_data.size();

            if(data_length==read_data.size()){ //数据是否接收完成。

    //            qDebug()<<read_data;

                router(); //完成时调用路由

            }

            m_tcpBlockSize=1; //设置为1表示后面的包不在是第一个数据包

            cc.device()->close();

        }else { //不是第一个包时执行

            QByteArray dd=this->readAll(); 

            QDataStream cc(&dd,QIODevice::ReadWrite);

            while (!cc.atEnd()) {

                unsigned char tmp_char;

                cc>>tmp_char;

                read_data.append(tmp_char);

            }

            if(data_length==read_data.size()){

                router();

            }

            cc.device()->close();

        }

    }

    void tcp_socket::router(){ //路由部分

        if(QJsonDocument::fromJson(read_data).isObject()){

    //        qDebug()<<read_data;

            QJsonObject data=QJsonDocument::fromJson(read_data).object();

            if(data.keys().contains("type")){

                QString type=data.value("type").toString();

                if(type=="last_temperatuer"){

                    //返回最后一次温度

                    QJsonObject data_send;

                    data_send.insert("type","last_temperatuer");

                    data_send.insert("data",last_temperatuer);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if(type=="last_wendu_collector"){

                    // insert 返回最后一次温度

                    QJsonArray tmp_arry;

                    QJsonObject send_data=data.value("data").toObject();

                    last_temperatuer=tmp_arry;

                    for(int i=0;i<send_data.keys().length();i++){

                        QString key=send_data.keys()[i];

                        QJsonObject tmp_data;

                        tmp_data.insert(key,send_data.value(key).toInt());

                        last_temperatuer.append(tmp_data);

                    }

                }

                else if (type=="temperatuer_day_hour") {

                    int day=data.value("day").toInt();

                    QString temperatuer_type=data.value("temperatuer_type").toString();

                    QJsonArray data_list=db.day_hour_temperatuer(day,temperatuer_type);

                    QJsonObject data_send;

                    data_send.insert("type","temperatuer_day_hour");

                    data_send.insert("data",data_list);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if (type=="temperatuer_ri") {

                    //按日返回

                    QString temperatuer_type=data.value("temperatuer_type").toString();

                    QJsonArray data_list=db.temperatuer_ri(temperatuer_type);

                    QJsonObject data_send;

                    data_send.insert("type","temperatuer_ri");

                    data_send.insert("data",data_list);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if (type=="temperatuer_yue") {

    //                qDebug()<<type;

                    //按日返回

                    QString temperatuer_type=data.value("temperatuer_type").toString();

    //                sql db;

                    QJsonArray data_list=db.temperatuer_yue(temperatuer_type);

                    QJsonObject data_send;

                    data_send.insert("type","temperatuer_yue");

                    data_send.insert("data",data_list);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if (type=="temperatuer_zhou") {

    //                qDebug()<<type;

                    //按周返回

                    QString temperatuer_type=data.value("temperatuer_type").toString();

                    QJsonArray data_list=db.temperatuer_zhou(temperatuer_type);

                    QJsonObject data_send;

                    data_send.insert("type","temperatuer_zhou");

                    data_send.insert("data",data_list);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if (type=="temperatuer_yue") {

                    //按月返回

                    QString temperatuer_type=data.value("temperatuer_type").toString();

                    QJsonArray data_list=db.temperatuer_yue(temperatuer_type);

                    QJsonObject data_send;

                    data_send.insert("type","temperatuer_yue");

                    data_send.insert("data",data_list);

                    QByteArray byte_data=QJsonDocument(data_send).toJson();

                    this->write(data_length_data(byte_data));

                }else if (type=="login") {

                    return_db(data,this);

                }else if (type=="on_off") {

                  QString user=data.value("user").toString();

                  int value=data.value("value").toInt();

                    QJsonObject on_off_status=db.set_action(user,type,value);

                    QJsonObject data_send;

                    data_send.insert("type","on_off");

                    data_send.insert("data",on_off_status);

                  this->write(data_length_data(QJsonDocument(data_send).toJson()));

                }else if (type=="set_moshi_leng_re") {

                    QString user=data.value("user").toString();

                    int value=data.value("value").toInt();

                    QJsonObject moshi_leng_re=db.set_action(user,type,value);

                    QJsonObject data_send;

                    data_send.insert("type","set_moshi_leng_re");

                    data_send.insert("data",moshi_leng_re);

                    this->write(data_length_data(QJsonDocument(data_send).toJson()));

                }

            }else {

                this->disconnect();

                this->close();

        }

        }else {

            this->disconnect();

            this->close();

        }

    }

    QByteArray tcp_socket::data_length_data(QByteArray data){

        QByteArray send_data;

        QDataStream bin_data(&send_data,QIODevice::ReadWrite);

        int data_length=data.size();

        bin_data<<(int)data_length;

        send_data.append(data);

        return send_data;

    }

    QByteArray tcp_server::data_length_data(QByteArray data){

        QByteArray send_data;

        QDataStream bin_data(&send_data,QIODevice::ReadWrite);

        int data_length=data.size();

        bin_data<<(int)data_length;

        send_data.append(data);

        return send_data;

    }

    ```

    相关文章

      网友评论

          本文标题:Qt tcp编程

          本文链接:https://www.haomeiwen.com/subject/dkgohctx.html