Qt tcp编程

注意:网络编程需要在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

#include

#include

#include

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

#include

#include

#include

#include

#include

#include

#include

#include

//#include

#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()<

    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()<

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

//            qDebug()<

            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()<

        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

                    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()<

                //按日返回

                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()<

                //按周返回

                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编程)