美文网首页
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编程

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

  • Qt5.8 (2).Java与Qt通信之TCP图片传输

    Java-Qt-TCP数据传输 程序描述 使用Qt建立TCP Server,用Java建立TCP Client,C...

  • QT-参考书

    《Qt Creator快速入门》《Qt5编程入门》 Qt进阶书籍推荐官方的《C++ GUI Qt4编程》

  • 《Qt高级编程》

    《Qt高级编程》,作者: (英)Mark Summerfield ,《qt高级编程》以工程实践为主旨,是对qt现有...

  • Qt高级编程

    《Qt高级编程》,作者: (英)Mark Summerfield ,《qt高级编程》以工程实践为主旨,是对qt现有...

  • 四 . TCP 编程

    什么是 TCP 编程 TCP 编程是建立在 TCP 协议上的 Socket 编程 什么是 TCP 协议 TCP (...

  • QT初学者入门

    Qt编程指南

  • Qt编程指南

    Qt编程指南 序言本教程《Qt编程指南》主要是写给Qt开发新手看的,当然前提必须学会C++,推荐《C++ Prim...

  • Qt分布式网络邻居TCP数据传输案例

    刚实现的跨平台Qt的网络邻居之TCP加网络编程中的广播实现,有需要的同学看看吧。 最原始的版本,目前正在改进的。不...

  • QT串口编程 - QSerialPort类

    QT串口编程 - QSerialPort类 提供对串口的访问 头文件:#include qmake: QT += ...

网友评论

      本文标题:Qt tcp编程

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