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 <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;

}

```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343