QT TCPSocket和QTCPServer使用


概述:QTcpSocket和QTcpServer可以實現TCP客戶端和服務器端通信,本文介紹基於塊的通信方式

基於塊的傳輸協議把數據作為二進制塊進行傳輸。每一個塊都由一個大小字段及其包含的數據域組成

程序界面

 

 一個數服務端socket一個是客戶端socket,客戶端socket可以從服務器端socket下載文件

 

運行過程

 

 客戶端精度條顯示文件下載進度。

 

 

test.rar表示服務器要發送的文件,testreceived.rar表示客戶端收到的文件

 

 因為測試服務器和客戶端在同一目錄下,所以該程序把收到的test.rar命名為testreceived.rar,以做區分

核心代碼

connect(&tcpSocketClient,&QTcpSocket::connected,this,&FileTransferSocket::slotConnected);
connect(&tcpSocketClient,&QTcpSocket::disconnected,this,&FileTransferSocket::slotDisconnected);
connect(&tcpSocketClient,&QTcpSocket::readyRead,this,&FileTransferSocket::slotReadyRead);
connect(&tcpSocketClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slotError(QAbstractSocket::SocketError)));

 

slotReadyRead當對方socket有數據過來將會調用此槽函數

1、tcpSocketClient.connectToHost("127.0.0.1",8888);

連接到服務器端socket

2、發送數據到連接的socket

QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_1);
out<<quint16(0)<<QString("downrequest");
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
tcpSocketClient.write(block);

每次發送數據都是以塊為單位的,上面代碼發送一個塊的數據

但是需要注意的地方是,數據在網絡傳輸中並不是以塊為單位,也就是發送一整塊數據,接收的socket可能不是一次正好接收一整個塊

可能收到一個完整的塊或者一個塊的一部分、一個塊和另一個塊的一部分、若干個塊或者亦可能是所有的塊,在接收端socket需要判斷。

先看看塊的結構形式

 

 

一個塊包含兩部分,一部分表示數據區域的大小,一部分表示數據區域

 

out<<quint16(0)<<QString("downrequest");

 

這段代碼的quint16(0)用來存放數據區域的大小,QString("downrequest")表示數據區域

 

out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));

 

這兩行代碼,分別是移到首位置,即數據數據區域大小

 

然后給數據區域填充數據的實際大小值.

 

 

3、我們來看看接收端socket如何接收數據

 

 

 

在這里定義一個nextBlockSize變量

用來存放每個塊的大小。

 

bytesAvailable()表示網絡里面傳過來的可用字節數,如果可用字節數已經大於或者等於sizeof(quint16)

還記得quint16表示什么嗎?這個區域存放的就是塊的數據區域大小。

如果可用字節數已經大於或者等於sizeof(quint16),這樣我們就可以取出這個塊的數據區域大小

in >> nextBlockSize;

然后再判斷bytesAvailable()是否大於等於nextBlockSize如果不是說明這個塊的數據還未完全傳過來,等待網絡數據傳輸(千萬不要取已接收的數據,因為是不完整的)

如果大於等於nextBlockSize,說明這一塊的數據區域已經完全傳過來了。

//數據塊完整可以接收
QString clientrequest;
in >> clientrequest;

然后把數據區域的數據放到clientrequest里面。

到此通過塊的形式發送數據就完成了

4、下面開始文件的傳輸

 

 先獲取本地文件,打文件大小文件名稱等信息傳到客戶端socket,當然上面代碼是寫死的文件名,你可以通過file直接獲取文件名。

上面的代碼還未正式發送文件,只是把文件的一些信息發送給客戶端socket。

5、

connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(slotBytesWritten(qint64)));

bytesWritten(qint64))這個信號每次數據寫入設備后會激發

 

在此槽函數里面讀取文件並發送文件到客戶端

文件分多次發送,每當有數據寫入的設備改槽函數都執行,直到文件發送完畢

6.我們再看看文件接收端

 

 這里就不做詳細講解了,主要就是從sokcet讀取說有數據,然后文件寫入

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM