Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能_第1頁(yè)
Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能_第2頁(yè)
Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能_第3頁(yè)
Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能_第4頁(yè)
Qt多線程實(shí)現(xiàn)網(wǎng)絡(luò)發(fā)送文件功能_第5頁(yè)
已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論