Qt tcp編程

注意:網(wǎng)絡(luò)編程需要在pro文件里添加 network,如該用到qSqldatabase 需要添加sql

例:

QT+= network\

? ? sql

#一侠姑、QTcpsocket:


QTcpsocet 是QT提供的tcp/ip的四層socket類.TCP(傳輸控制協(xié)議)是一種可靠的嗦明,面向流的廉赔,面向連接的傳輸協(xié)議灸叼。它特別適用于連續(xù)傳輸數(shù)據(jù)汉额。

QTcpsocket 是QAbstractSocket的子類.

方法:

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

?QTcpsocket::write(QBytearry) //數(shù)據(jù)的寫入

虛構(gòu)函數(shù):

void QTcpsocket::readyRead() //實現(xiàn)接收到數(shù)據(jù)時執(zhí)行

二、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(); //構(gòu)造函數(shù)

? ? QByteArray data_length_data(QByteArray data);? //用于對要發(fā)送的數(shù)據(jù)頭部添加包長度被冒。

protected:

? ? void incomingConnection(qintptr soketnember); //有新連接時執(zhí)行军掂,創(chuàng)造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(); //接收數(shù)據(jù)路由蝗锥。

? ? QByteArray data_length_data(QByteArray data); //對發(fā)送的數(shù)據(jù)添加包長度

private:

? ? int m_tcpBlockSize = 0;? ? ? ? //數(shù)據(jù)包長度計算

? ? bool is_one;? ? ? ? ? ? ? ? ? ? //是否是第一個數(shù)據(jù)包

? ? int data_length;? ? ? ? ? ? //數(shù)據(jù)包長度

? ? QByteArray read_data;? ? //數(shù)據(jù)包緩存(在接收到的數(shù)據(jù)包未達(dá)到第一個包描述的大小時緩存用)

? ? //sql db;

signals:

? ? ? ? void return_db(QJsonObject user_passwd,QTcpSocket *tcpsocket); //查詢數(shù)據(jù)庫信號,qsqldatabase 的多線程問題率触,所有發(fā)送信號到主進(jìn)程终议。

private slots:

? ? void Read_data(); //有數(shù)據(jù)進(jìn)來時調(diào)用

};

#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"? //數(shù)據(jù)庫查詢,寫入部分葱蝗,于本筆記無關(guān)可忽略

#include "cache.h" //全局變量穴张,用于緩存最后一次的值,于本筆記無關(guān)两曼,可忽略

tcp_server::tcp_server()

{

}

void tcp_server::incomingConnection(qintptr soketnember){ //有新連接時執(zhí)行

? ? tcp_socket * socket=new tcp_socket(soketnember); //創(chuàng)建一個socket連接指針并按“本機(jī)套接字描述符”創(chuàng)建

? ? QThread *task=new QThread(); 創(chuàng)建一個線程地址皂甘。

? ? connect(socket,SIGNAL(disconnected()),task,SLOT(quit()));? //socket斷開連接時退出線程

? ? connect(socket,SIGNAL(readyRead()),socket,SLOT(Read_data())); //有數(shù)據(jù)傳入時執(zhí)行Read_data()槽

? ? connect(socket,SIGNAL(return_db(QJsonObject,QTcpSocket*)),this,SLOT(socket_write(QJsonObject,QTcpSocket*))); //用于解決QSqldatabase 多線程問題,在需要查詢數(shù)據(jù)庫時發(fā)送給主進(jìn)程執(zhí)行悼凑,由主進(jìn)程直接返回給客戶端的socket 偿枕。

? ? socket->moveToThread(task); //移動socket 到線程

? ? task->start(); //線程啟動

}

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

? ? sql db; //初始化數(shù)據(jù)庫類,此類為自定義類佛析,與本筆記無關(guān)

? ? 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); //寫超時設(shè)定為1秒益老。

}

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

{

? ? this->setSocketDescriptor(soketDescriptor); //設(shè)置這個連接的描述符是由QTcpserver傳入的連接描述符彪蓬。

}

void tcp_socket::Read_data(){? //讀取數(shù)據(jù)

? ? if(m_tcpBlockSize==0){ //判斷已接收的數(shù)據(jù)是否為0,0表示第一個數(shù)據(jù)包寸莫。

? ? ? QByteArray dd=this->readAll(); //讀出所有數(shù)據(jù)。

? ? ? QDataStream cc(&dd,QIODevice::ReadWrite); //以流數(shù)據(jù)方式打開

? ? ? cc.device()->seek(0); //設(shè)置數(shù)據(jù)指針為0.

? ? ? cc>>data_length; //獲取數(shù)據(jù)包大小档冬。所以要求客戶段傳來的數(shù)據(jù)包前4個byte時int的包大小膘茎。

? ? ? if(!data_length>8){

? ? ? ? ? this->disconnect();

? ? ? ? ? this->close();

? ? ? }

// 包描述: qbytearry [int(包大小),xxxxxxxxxxxxxxxxxxxxxxx.......數(shù)據(jù)部分]

? ? ? cc.device()->seek(sizeof(int)); //移動指針到包大小描述后的數(shù)據(jù)開始位。

? ? ? ? while (!cc.atEnd()) { //循環(huán)判斷數(shù)據(jù)是否讀取到結(jié)尾

? ? ? ? ? ? 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()){ //數(shù)據(jù)是否接收完成披坏。

//? ? ? ? ? ? qDebug()<<read_data;

? ? ? ? ? ? router(); //完成時調(diào)用路由

? ? ? ? }

? ? ? ? m_tcpBlockSize=1; //設(shè)置為1表示后面的包不在是第一個數(shù)據(jù)包

? ? ? ? cc.device()->close();

? ? }else { //不是第一個包時執(zhí)行

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

}

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盐数,隨后出現(xiàn)的幾起案子棒拂,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帚屉,死亡現(xiàn)場離奇詭異谜诫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)攻旦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門喻旷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人牢屋,你說我怎么就攤上這事且预。” “怎么了烙无?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵锋谐,是天一觀的道長。 經(jīng)常有香客問我截酷,道長怀估,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任合搅,我火速辦了婚禮多搀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灾部。我一直安慰自己康铭,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布赌髓。 她就那樣靜靜地躺著从藤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锁蠕。 梳的紋絲不亂的頭發(fā)上夷野,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音荣倾,去河邊找鬼悯搔。 笑死,一個胖子當(dāng)著我的面吹牛舌仍,可吹牛的內(nèi)容都是我干的妒貌。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼铸豁,長吁一口氣:“原來是場噩夢啊……” “哼灌曙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起节芥,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤在刺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚣驼,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡忍燥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了隙姿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梅垄。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖输玷,靈堂內(nèi)的尸體忽然破棺而出队丝,到底是詐尸還是另有隱情,我是刑警寧澤欲鹏,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布机久,位于F島的核電站,受9級特大地震影響赔嚎,放射性物質(zhì)發(fā)生泄漏膘盖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一尤误、第九天 我趴在偏房一處隱蔽的房頂上張望侠畔。 院中可真熱鬧,春花似錦损晤、人聲如沸软棺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喘落。三九已至,卻和暖如春最冰,著一層夾襖步出監(jiān)牢的瞬間瘦棋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工暖哨, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留赌朋,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓鹿蜀,卻偏偏與公主長得像箕慧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茴恰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361