版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能本文實(shí)例為大家分享了Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能的具體代碼,供大家參考,具體內(nèi)容如下
客戶(hù)端給服務(wù)器發(fā)送文件,服務(wù)器進(jìn)行接收文件的簡(jiǎn)單操作
1.服務(wù)器
1.創(chuàng)建QTcpServer類(lèi)的對(duì)象
QTcpServer*server=newQTcpServer(this);
2.進(jìn)行監(jiān)聽(tīng)
boolQTcpServer::listen(constQHostAddressaddress=QHostAddress::Any,quint16port=0)
3.通過(guò)接收QTcpServer發(fā)出的newConnection的信號(hào),進(jìn)行下一步操作
[signal]voidQTcpServer::newConnection()
4.通過(guò)調(diào)用nextPendingConnection方法獲取套接字
//通過(guò)this-m_server調(diào)用nextPendConnection
QTcpSocket*socket=server-nextPendingConnection();
5.接收客戶(hù)端發(fā)來(lái)是消息通過(guò)[signal]voidQIODevice::readyRead()信號(hào)
6.客戶(hù)端下線[signal]voidQAbstractSocket::disconnected()信號(hào)表示
創(chuàng)建一個(gè)子線程類(lèi),繼承QThread,重寫(xiě)父類(lèi)的run()方法
在run方法中,創(chuàng)建文件,接收客戶(hù)端發(fā)的文件寫(xiě)進(jìn)創(chuàng)建的文件中;
接收文件時(shí),要先獲取第一次客戶(hù)端發(fā)來(lái)的文件大?。?/p>
獲取客戶(hù)端第一次發(fā)來(lái)的文件大小
//進(jìn)行接收數(shù)據(jù)的時(shí)候,需要知道客戶(hù)端發(fā)來(lái)的文件的大小
//先將客戶(hù)端第一次發(fā)來(lái)的數(shù)據(jù)的大小讀取出來(lái)
staticintcount=0;
//判斷是否是客戶(hù)端第一次發(fā)來(lái)的數(shù)據(jù)
staticinttotal=0;
//記錄文件的大小
if(count==0)
{
this-m_tcp-read((char*)total,4);
//獲取文件大小
}
創(chuàng)建子線程類(lèi)并啟動(dòng)子線程
//創(chuàng)建子線程類(lèi)對(duì)象
MyQThread*myqtread=newMyQThread;
//啟動(dòng)子線程
myqtread-start();
服務(wù)端代碼:
widget.h主線程頭文件
#ifndefWIDGET_H
#defineWIDGET_H
#includeQWidget
#includeQTcpServer
namespaceUi{
classWidget;
classWidget:publicQWidget
Q_OBJECT
public:
explicitWidget(QWidget*parent=0);
~Widget();
privateslots:
voidon_listenBtn_clicked();
private:
//創(chuàng)建QTcpServer類(lèi)的對(duì)象
QTcpServer*m_server;
private:
Ui::Widget*ui;
#endif//WIDGET_H
widget.cpp主線程:
#include"widget.h"
#include"ui_widget.h"
#include"myqthread.h"
#includeQMessageBox
Widget::Widget(QWidget*parent):
QWidget(parent),
ui(newUi::Widget)
ui-setupUi(this);
//設(shè)置端口號(hào)
ui-port-setText("8989");
//利用多線程進(jìn)行鏈接服務(wù)器
//1.需要?jiǎng)?chuàng)建一個(gè)線程類(lèi)的子類(lèi),讓其繼承Qt中的線程QThread
//2.重寫(xiě)父類(lèi)的run()方法,在該函數(shù)內(nèi)部編寫(xiě)子線程要處理的具體業(yè)務(wù)流程
//3.在主線程中創(chuàng)建子線程對(duì)象,new一個(gè)就可以
//4.啟動(dòng)子線程,調(diào)用start()方法
//實(shí)例化QTcpServer對(duì)象
this-m_server=newQTcpServer(this);
//檢驗(yàn)是否接收客戶(hù)端的連接
connect(this-m_server,QTcpServer::newConnection,this,[=]()
{
//獲取套接字
QTcpSocket*tcp=this-m_server-nextPendingConnection();
//創(chuàng)建子線程類(lèi)對(duì)象
MyQThread*myqtread=newMyQThread(tcp);
//啟動(dòng)子線程
myqtread-start();
//獲取子線程中發(fā)來(lái)的客戶(hù)端端口的消息
connect(myqtread,MyQThread::ClientDisconnect,this,[=]()
{
//彈出對(duì)話(huà)框提示
QMessageBox::warning(this,"警告","客戶(hù)端已斷開(kāi)連接...");
});
//接收接收完客戶(hù)端的信號(hào)
connect(myqtread,MyQThread::OverRecveid,this,[=]()
{
//彈出對(duì)話(huà)框提示
QMessageBox::information(this,"提示","已接收文客戶(hù)端發(fā)來(lái)的數(shù)據(jù)");
//關(guān)閉套接字
tcp-close();
//釋放
tcp-deleteLater();
//釋放線程
myqtread-quit();
myqtread-wait();
myqtread-deleteLater();
});
});
Widget::~Widget()
deleteui;
//點(diǎn)擊監(jiān)聽(tīng)按鈕進(jìn)行監(jiān)聽(tīng)按鈕轉(zhuǎn)到槽的方式
voidWidget::on_listenBtn_clicked()
//獲取端口號(hào)
unsignedshortport=ui-port-text().toUShort();
//利用this-m_s調(diào)用listen進(jìn)行監(jiān)聽(tīng)
this-m_server-listen(QHostAddress::Any,port);
}
myqthread.h子線程頭文件
#ifndefMYQTHREAD_H
#defineMYQTHREAD_H
//#includeQObject
#includeQTcpSocket
#includeQThread
classMyQThread:publicQThread
Q_OBJECT
public:
explicitMyQThread(QTcpSocket*tcp,QObject*parent=nullptr);
//2.重寫(xiě)QThread類(lèi)中的受保護(hù)成員run()方法
protected:
voidrun();
public:
//自定義套接字對(duì)象記錄主線程傳進(jìn)的套接字對(duì)象tcp
QTcpSocket*m_tcp;
signals:
//自定義信號(hào)將服務(wù)器接收完客戶(hù)端發(fā)來(lái)的數(shù)據(jù)告訴主線程
voidOverRecveid();
//自定義信號(hào)將客戶(hù)端斷開(kāi)連接告訴主線程
voidClientDisconnect();
publicslots:
#endif//MYQTHREAD_H
myqthread.cpp子線程文件
#include"myqthread.h"
#includeQFile
MyQThread::MyQThread(QTcpSocket*tcp,QObject*parent):QThread(parent)
this-m_tcp=tcp;
//2.重寫(xiě)QThread類(lèi)中的受保護(hù)成員run()方法
voidMyQThread::run()
//1.創(chuàng)建文件打開(kāi)文件
QFile*file=newQFile("recv.txt");
file-open(QFile::WriteOnly);
//以只寫(xiě)的方式打開(kāi)文件
//2.檢驗(yàn)是否進(jìn)行讀寫(xiě)
connect(this-m_tcp,QTcpSocket::readyRead,this,[=]()
{
//進(jìn)行接收數(shù)據(jù)的時(shí)候,需要知道客戶(hù)端發(fā)來(lái)的文件的大小
//先將客戶(hù)端第一次發(fā)來(lái)的數(shù)據(jù)的大小讀取出來(lái)
staticintcount=0;
//判斷是否是客戶(hù)端第一次發(fā)來(lái)的數(shù)據(jù)
staticinttotal=0;
//記錄文件的大小
if(count==0)
{
this-m_tcp-read((char*)total,4);
//獲取文件大小
}
//將剩下的數(shù)據(jù)全部讀取出來(lái)
//獲取客戶(hù)端發(fā)來(lái)的數(shù)據(jù)
QByteArrayrecvClient=this-m_tcp-readAll();//全部接收
//將讀取的數(shù)據(jù)的量記錄到count中
count+=recvClient.size();
//將數(shù)據(jù)寫(xiě)進(jìn)文件中
file-write(recvClient);
//判斷服務(wù)器是否把客戶(hù)端發(fā)來(lái)的數(shù)據(jù)全部讀取完
if(count==total)
{
//關(guān)閉套接字
this-m_tcp-close();
//釋放套接字
this-m_tcp-deleteLater();
//關(guān)閉文件
file-close();
file-deleteLater();
//自定義一個(gè)信號(hào)告訴主線程文件已接收完畢
emitOverRecveid();
}
});
//3.檢驗(yàn)客戶(hù)端是否斷開(kāi)連接
connect(m_tcp,QTcpSocket::disconnected,this,[=]()
{
//將客戶(hù)端斷開(kāi)連接發(fā)送給主線程
emitthis-ClientDisconnect();
});
//調(diào)用exec進(jìn)入事件循環(huán)阻塞
exec();
}
2.客戶(hù)端
1.綁定ip和端口號(hào)
[virtual]voidQAbstractSocket::connectToHost(constQStringhostName,quint16port,OpenModeopenMode=ReadWrite,NetworkLayerProtocolprotocol=AnyIPProtocol)
2.連接服務(wù)器
[signal]voidQAbstractSocket::connected()
3.通過(guò)套接字調(diào)用write方法發(fā)送消息給服務(wù)器
qint64QIODevice::write(constchar*data,qint64maxSize)
4.斷開(kāi)連接
[signal]voidQAbstractSocket::disconnected()
利用多線程實(shí)現(xiàn)選擇文件發(fā)送文件
利用第二種多線程的方法
1.創(chuàng)建一個(gè)新的類(lèi),讓這個(gè)類(lèi)從QObject中派生
2.在這個(gè)新的類(lèi)中添加一個(gè)公有的成員函數(shù),函數(shù)體是我們要子線程中執(zhí)行的業(yè)務(wù)邏輯
3.在主線程中創(chuàng)建一個(gè)QThread對(duì)象,這個(gè)就是子線程的對(duì)象
4.在主線程中創(chuàng)建一個(gè)工作類(lèi)的對(duì)象
5.將工作類(lèi)對(duì)象移動(dòng)到子線程對(duì)象中,需要調(diào)用QObject類(lèi)提供的moveThread
6.啟動(dòng)子線程,調(diào)用start()這個(gè)線程啟動(dòng)了,當(dāng)時(shí)移動(dòng)到線程中的對(duì)象并沒(méi)有工作
7.調(diào)用工作類(lèi)的對(duì)象函數(shù),讓這個(gè)函數(shù)開(kāi)始執(zhí)行,這個(gè)時(shí)候是在移動(dòng)到那個(gè)子線程中運(yùn)行的。
客戶(hù)端代碼:
mythread.h任務(wù)類(lèi)頭文件
#ifndefMYTHREAD_H
#defineMYTHREAD_H
#includeQObject
#includeQTcpSocket
classMyThread:publicQObject
Q_OBJECT
public:
explicitMyThread(QObject*parent=nullptr);
//連接服務(wù)器
voidconnectToServer(unsignedshortport,QStringip);
//發(fā)送文件
voidSendFile(QStringpath);
private:
//創(chuàng)建QTcpSocket類(lèi)的對(duì)象
QTcpSocket*m_socket;
signals:
//自定義一個(gè)信息告訴主線程成功連接到服務(wù)器
voidConnectOK();
//自定義一個(gè)信號(hào)告訴主線程服務(wù)器已斷開(kāi)連接
voidgameOver();
//自定義一個(gè)信號(hào)將獲取的百分比發(fā)送給主線程
voidSendPercent(int);
publicslots:
#endif//MYTHREAD_H
mythread.cpp任務(wù)類(lèi)文件
#include"mythread.h"
#includeQFileInfo
#includeQMessageBox
MyThread::MyThread(QObject*parent):QObject(parent)
//連接服務(wù)器
voidMyThread::connectToServer(unsignedshortport,QStringip)
//實(shí)例化socket類(lèi)的對(duì)象
this-m_socket=newQTcpSocket(this);
//嘗試與服務(wù)器取得連接綁定IP和端口號(hào)
this-m_socket-connectToHost(ip,port);
//檢驗(yàn)是否成功與服務(wù)器取等連接
connect(this-m_socket,QTcpSocket::connected,this,[=]()
{
emitthis-ConnectOK();//自定義一個(gè)信號(hào)告訴主線程成功連接上服務(wù)器
});
//檢驗(yàn)服務(wù)器是否斷開(kāi)連接
connect(this-m_socket,QTcpSocket::disconnected,this,[=]()
{
this-m_socket-close();
//關(guān)閉套接字
emitthis-gameOver();
//發(fā)送信號(hào)告訴主線程服務(wù)器已斷開(kāi)連接
});
//發(fā)送文件
voidMyThread::SendFile(QStringpath)
//1.獲取文件大小
QFileInfoinfo(path);
intfileSize=info.size();
//2.打開(kāi)文件
QFilefile(path);
boolret=file.open(QFile::ReadOnly);
if(!ret)
{
QMessageBox::warning(NULL,"警告","打開(kāi)文件失敗");
return;//退出函數(shù)
}
//判斷什么時(shí)候讀完文件
while(!file.atEnd())
{
//第一次發(fā)送文件的時(shí)候?qū)⑽募拇笮“l(fā)送給服務(wù)器
//定義一個(gè)標(biāo)記當(dāng)標(biāo)記為0時(shí),表示第一次發(fā)送文件
staticintnum=0;
if(num==0)
{
this-m_socket-write((char*)fileSize,4);//將文件大小發(fā)送給服務(wù)器
}
//在循環(huán)體中每次讀取一行
QByteArrayline=file.readLine();
//每次發(fā)送一次數(shù)據(jù),就將發(fā)送的數(shù)據(jù)的量記錄下來(lái)用于更新進(jìn)度條
num+=line.size();
//基于num值計(jì)算百分比
intpercent=(num*100/fileSize);
//將百分比發(fā)送給主線程
emitthis-SendPercent(percent);
//將讀取的數(shù)據(jù)通過(guò)套接字對(duì)象發(fā)送給服務(wù)器
this-m_socket-write(line);
}
}
widget.h主線程頭文件
#ifndefWIDGET_H
#defineWIDGET_H
#includeQWidget
namespaceUi{
classWidget;
classWidget:publicQWidget
Q_OBJECT
public:
explicitWidget(QWidget*parent=0);
~Widget();
signals:
//自定義一個(gè)信號(hào)告訴子線程進(jìn)行鏈接服務(wù)器
voidTellToConnect(unsignedshortport,QStringip);
//自定義一個(gè)信號(hào)將選中的文件路徑發(fā)送給任務(wù)類(lèi)
voidSendToFile(QString);
privateslots:
voidon_connectBtn_clicked();
voidon_selectBtn_clicked();
voidon_sendBtn_clicked();
private:
QStringm_path;
private:
Ui::Widget*ui;
#endif//WIDGET_H
widget.cpp
#include"widget.h"
#include"ui_widget.h"
#includeQFileDialog
#includeQMessageBox
#includeQThread
#include"mythread.h"
Widget::Widget(QWidget*parent):
QWidget(parent),
ui(newUi::Widget)
ui-setupUi(this);
//利用多線程實(shí)現(xiàn)選擇文件發(fā)送文件
//利用第二種多線程的方法
//1.創(chuàng)建一個(gè)新的類(lèi),讓這個(gè)類(lèi)從QObject中派生
//2.在這個(gè)新的類(lèi)中添加一個(gè)公有的成員函數(shù),函數(shù)體是我們要子線程中執(zhí)行的業(yè)務(wù)邏輯
//3.在主線程中創(chuàng)建一個(gè)QThread對(duì)象,這個(gè)就是子線程的對(duì)象
//4.在主線程中創(chuàng)建一個(gè)工作類(lèi)的對(duì)象
//5.將工作類(lèi)對(duì)象移動(dòng)到子線程對(duì)象中,需要調(diào)用QObject類(lèi)提供的moveThread方法
//6.啟動(dòng)子線程,調(diào)用start()這個(gè)線程啟動(dòng)了,當(dāng)時(shí)移動(dòng)到線程中的對(duì)象并沒(méi)有工作
//7.調(diào)用工作類(lèi)的對(duì)象函數(shù),讓這個(gè)函數(shù)開(kāi)始執(zhí)行,這個(gè)時(shí)候是在移動(dòng)到那個(gè)子線程中運(yùn)行的。
//1.創(chuàng)建QThread對(duì)象
QThread*t=newQThread;
//2.創(chuàng)建任務(wù)類(lèi)的對(duì)象
MyThread*working=newMyThread;
//3.將任務(wù)類(lèi)對(duì)象移動(dòng)到子線程中
working-moveToThread(t);
//啟動(dòng)子線程
t-start();
//4.設(shè)置IP端口號(hào)
ui-ip_lineEide-setText("127.0.0.1");
ui-port_lineEdit-setText("8989");
//5.設(shè)置進(jìn)度條
ui-progressBar-setRange(0,100);
//進(jìn)度條的范圍
ui-progressBar-setValue(0);
//初始化為0
//6.更新進(jìn)度條通過(guò)連接任務(wù)類(lèi)發(fā)來(lái)的信號(hào)實(shí)現(xiàn)
connect(working,MyThread::SendPercent,ui-progressBar,QProgressBar::setValue);
//7.接收任務(wù)類(lèi)發(fā)來(lái)的成功連接到服務(wù)器信號(hào)
connect(working,MyThread::ConnectOK,this,[=]()
{
QMessageBox::information(this,"提示","成功連接到服務(wù)器");
//將文件按鈕設(shè)置成不可用狀態(tài)
ui-sendBtn-setDisabled(false);
});
//8.連接任務(wù)類(lèi)發(fā)來(lái)的斷開(kāi)連接的信號(hào)
connect(working,MyThread::gameOver,this,[=]()
{
QMessageBox::warning(this,"警告","服務(wù)器已斷開(kāi)連接");
//釋放支援
t-quit();
t-wait();
t
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 小快餐店衛(wèi)生管理制度
- 天貓運(yùn)營(yíng)崗位薪資制度
- 光伏薄膜組件制造工安全綜合能力考核試卷含答案
- 數(shù)控機(jī)床裝調(diào)維修工保密競(jìng)賽考核試卷含答案
- 預(yù)拌混凝土中控工安全意識(shí)強(qiáng)化能力考核試卷含答案
- 道路巡視養(yǎng)護(hù)工復(fù)測(cè)能力考核試卷含答案
- 老年人入住登記及檔案管理制度
- 酒店客房服務(wù)質(zhì)量制度
- 酒店安全疏散逃生演練制度
- 超市顧客投訴處理制度
- 頸內(nèi)靜脈血栓的護(hù)理
- 操作工技能等級(jí)評(píng)級(jí)方案
- 國(guó)家職業(yè)技術(shù)技能標(biāo)準(zhǔn) 5-05-02-01 農(nóng)作物植保員 人社廳發(fā)202021號(hào)
- 購(gòu)房委托書(shū)范文
- 素描第2版(藝術(shù)設(shè)計(jì)相關(guān)專(zhuān)業(yè))全套教學(xué)課件
- 新生兒先天性腎上腺皮質(zhì)增生癥
- 中國(guó)傳統(tǒng)木雕工藝美術(shù)的繼承與發(fā)展-以平遙木雕神像傳統(tǒng)技藝為例
- (完整版)四宮格數(shù)獨(dú)題目204道(可直接打印)及空表(一年級(jí)數(shù)獨(dú)題練習(xí))
- DB32/T+4539-2023+淡水生物環(huán)境DNA監(jiān)測(cè)技術(shù)方法
- 火電廠鍋爐運(yùn)行與維護(hù)
- CTM系列產(chǎn)品使用手冊(cè)
評(píng)論
0/150
提交評(píng)論