成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

解析 Qt網絡之TCP 下篇 網絡學習基礎

移動開發
本節接著上節繼續講,我們重新寫一個客戶端程序和一個服務器程序,這次我們讓客戶端進行文件的發送,服務器進行文件的接收。

解析 Qt網絡TCP 下篇 網絡學習基礎是本文要介紹的內容,接著上一篇繼續介紹。解析Qt網絡之TCP 上篇 網絡學習基礎 在上一節里我們使用TCP服務器發送一個字符串,然后在TCP客戶端進行接收。在這一節我們重新寫一個客戶端程序和一個服務器程序,這次我們讓客戶端進行文件的發送,服務器進行文件的接收。有了上一節的基礎,這一節的內容就很好理解了,注意一下幾個信號和槽的關聯即可。當然,我們這次要更深入了解一下數據的發送和接收的處理方法。

一、客戶端

這次我們先講解客戶端,在客戶端里我們與服務器進行連接,一旦連接成功,就會發出connected()信號,這時我們就進行文件的發送。

在上一節我們已經看到,發送數據時我們先發送了數據的大小信息。這一次,我們要先發送文件的總大小,然后文件名長度,然后是文件名,這三部分我們合稱為文件頭結構,最后再發送文件數據。所以在發送函數里我們就要進行相應的處理,當然,在服務器的接收函數里我們也要進行相應的處理。對于文件大小,這次我們使用了qint64,它是64位的,可以表示一個很大的文件了。

1.同前一節,我們新建工程,將工程命名為“tcpSender”。注意添加network模塊。

2.我們在widget.ui文件中將界面設計如下。

Qt網絡之TCP 下篇 網絡學習基礎
這里“主機”后的Line Edit的objectName為hostLineEdit;“端口”后的Line Edit的objectName為portLineEdit;下面的Progress Bar的objectName為clientProgressBar,其value屬性設為0;“狀態”Label的objetName為clientStatusLabel;“打開”按鈕的objectName為openButton;“發送”按鈕的objectName為sendButton;

3.在widget.h 文件中進行更改。

(1)添加頭文件#include <QtNetwork>

(2)添加private變量:

  1. QTcpSocket *tcpClient;  
  2.     QFile *localFile;  //要發送的文件  
  3.     qint64 totalBytes;  //數據總大小  
  4.     qint64 bytesWritten;  //已經發送數據大小  
  5.     qint64 bytesToWrite;   //剩余數據大小  
  6.     qint64 loadSize;   //每次發送數據的大小  
  7.     QString fileName;  //保存文件路徑  
  8. QByteArray outBlock;  //數據緩沖區,即存放每次要發送的數據 

(3)添加私有槽函數:

  1. private slots:  
  2.     void send();  //連接服務器  
  3.     void startTransfer();  //發送文件大小等信息  
  4.     void updateClientProgress(qint64); //發送數據,更新進度條  
  5.     void displayError(QAbstractSocket::SocketError); //顯示錯誤  
  6. void openFile();  //打開文件 

4.在widget.cpp文件中進行更改。

添加頭文件:#include <QFileDialog>

(1)在構造函數中添加代碼:

  1. loadSize = 4*1024;  
  2.     totalBytes = 0;  
  3.     bytesWritten = 0;  
  4.     bytesToWrite = 0;  
  5.     tcpClient = new QTcpSocket(this);  
  6.     connect(tcpClient,SIGNAL(connected()),this,SLOT(startTransfer()));  
  7.     //當連接服務器成功時,發出connected()信號,我們開始傳送文件  
  8.     connect(tcpClient,SIGNAL(bytesWritten(qint64)),this,  
  9. SLOT(updateClientProgress(qint64)));  
  10.     //當有數據發送成功時,我們更新進度條  
  11.     connect(tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,  
  12.             SLOT(displayError(QAbstractSocket::SocketError)));  
  13.     ui->sendButton->setEnabled(false);  
  14.     //開始使”發送“按鈕不可用 

我們主要是進行了變量的初始化和幾個信號和槽函數的關聯。

(2)實現打開文件函數。

  1. void Widget::openFile()   //打開文件  
  2. {  
  3.     fileName = QFileDialog::getOpenFileName(this);  
  4.     if(!fileName.isEmpty())  
  5.     {  
  6.         ui->sendButton->setEnabled(true);  
  7.         ui->clientStatusLabel->setText(tr(“打開文件 %1 成功!”)  
  8.                                        .arg(fileName));  
  9.     }  

該函數將在下面的“打開”按鈕單擊事件槽函數中調用。

(3)實現連接函數。

  1. void Widget::send()   //連接到服務器,執行發送  
  2. {  
  3.     ui->sendButton->setEnabled(false);  
  4.     bytesWritten = 0;  
  5.     //初始化已發送字節為0  
  6.     ui->clientStatusLabel->setText(tr(“連接中…”));  
  7.     tcpClient->connectToHost(ui->hostLineEdit->text(),  
  8.                             ui->portLineEdit->text().toInt());//連接  

該函數將在“發送”按鈕的單擊事件槽函數中調用。

(4)實現文件頭結構的發送。

  1. void Widget::startTransfer()  //實現文件大小等信息的發送  
  2. {  
  3.     localFile = new QFile(fileName);  
  4.     if(!localFile->open(QFile::ReadOnly))  
  5.     {  
  6.         qDebug() << "open file error!";  
  7.         return;  
  8.     }  
  9.     totalBytes = localFile->size();  
  10.     //文件總大小  
  11.     QDataStream sendOut(&outBlock,QIODevice::WriteOnly);  
  12.     sendOut.setVersion(QDataStream::Qt_4_6);  
  13.     QString currentFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);  
  14.     sendOut << qint64(0) << qint64(0) << currentFileName;  
  15.     //依次寫入總大小信息空間,文件名大小信息空間,文件名  
  16.     totalBytes += outBlock.size();  
  17.     //這里的總大小是文件名大小等信息和實際文件大小的總和  
  18.     sendOut.device()->seek(0);  
  19.     sendOut<<totalBytes<<qint64((outBlock.size() - sizeof(qint64)*2));  
  20.     //返回outBolock的開始,用實際的大小信息代替兩個qint64(0)空間  
  21.     bytesToWrite = totalBytes - tcpClient->write(outBlock);  
  22.     //發送完頭數據后剩余數據的大小  
  23.     ui->clientStatusLabel->setText(tr("已連接"));  
  24.     outBlock.resize(0);  

(5)下面是更新進度條,也就是發送文件數據。

  1. void Widget::updateClientProgress(qint64 numBytes) //更新進度條,實現文件的傳送  
  2. {  
  3.     bytesWritten += (int)numBytes;  
  4.     //已經發送數據的大小  
  5.     if(bytesToWrite > 0) //如果已經發送了數據  
  6.     {  
  7.         outBlock = localFile->read(qMin(bytesToWrite,loadSize));  
  8.       //每次發送loadSize大小的數據,這里設置為4KB,如果剩余的數據不足4KB,  
  9.       //就發送剩余數據的大小  
  10.         bytesToWrite -= (int)tcpClient->write(outBlock);  
  11.        //發送完一次數據后還剩余數據的大小  
  12.         outBlock.resize(0);  
  13.         //清空發送緩沖區  
  14.     }  
  15.     else  
  16.     {  
  17.         localFile->close(); //如果沒有發送任何數據,則關閉文件  
  18.     }  
  19.     ui->clientProgressBar->setMaximum(totalBytes);  
  20.     ui->clientProgressBar->setValue(bytesWritten);  
  21.     //更新進度條  
  22.     if(bytesWritten == totalBytes) //發送完畢  
  23.     {  
  24.         ui->clientStatusLabel->setText(tr(“傳送文件 %1 成功”).arg(fileName));  
  25.         localFile->close();  
  26.         tcpClient->close();  
  27.     }  

(6)實現錯誤處理函數。

  1. void Widget::displayError(QAbstractSocket::SocketError) //顯示錯誤  
  2. {  
  3.     qDebug() << tcpClient->errorString();  
  4.     tcpClient->close();  
  5.     ui->clientProgressBar->reset();  
  6.     ui->clientStatusLabel->setText(tr(“客戶端就緒”));  
  7.     ui->sendButton->setEnabled(true);  

(7)我們從widget.ui中分別進行“打開”按鈕和“發送”按鈕的單擊事件槽函數,然后更改如下。

  1. void Widget::on_openButton_clicked() //打開按鈕  
  2. {  
  3.     openFile();  
  4. }  
  5. void Widget::on_sendButton_clicked() //發送按鈕  
  6. {  
  7.     send();  

5.我們為了使程序中的中文不顯示亂碼,在main.cpp文件中更改。

添加頭文件:#include <QTextCodec>

在main函數中添加代碼:QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

6.運行程序,效果如下。

Qt網絡之TCP 下篇 網絡學習基礎

7.程序整體思路分析。

我們設計好界面,然后按下“打開”按鈕,選擇我們要發送的文件,這時調用了openFile()函數。然后我們點擊“發送”按鈕,調用send()函數,與服務器進行連接。當連接成功時就會發出connected()信號,這時就會執行startTransfer()函數,進行文件頭結構的發送,當發送成功時就會發出bytesWritten(qint64)信號,這時我們執行updateClientProgress(qint64 numBytes)進行文件數據的傳輸和進度條的更新。這里使用了一個loadSize變量,我們在構造函數中將其初始化為4*1024即4字節,它的作用是,我們將整個大的文件分成很多小的部分進行發送,每部分為4字節。而當連接出現問題時就會發出error(QAbstractSocket::SocketError)信號,這時就會執行displayError()函數。對于程序中其他細節我們就不再分析,希望大家能自己編程研究一下。

#p#

二、服務器端。

我們在服務器端進行數據的接收。服務器端程序是很簡單的,我們開始進行監聽,一旦發現有連接請求就發出newConnection()信號,然后我們便接受連接,開始接收數據。

1、新建工程,名字為“tcpReceiver”。

2、我們更改widget.ui文件,設計界面如下。

Qt網絡之TCP 下篇 網絡學習基礎

其中“服務器端”Label的objectName為serverStatusLabel;進度條Progress Bar的objectName為serverProgressBar,設置其value屬性為0;“開始監聽”按鈕的objectName為startButton。

效果如下。

3、更改widget.h文件的內容。

(1)添加頭文件:#include <QtNetwork>

(2)添加私有變量:

  1.  QTcpServer tcpServer;  
  2. QTcpSocket *tcpServerConnection;  
  3. qint64 totalBytes;  //存放總大小信息  
  4. qint64 bytesReceived;  //已收到數據的大小  
  5. qint64 fileNameSize;  //文件名的大小信息  
  6. QString fileName;   //存放文件名  
  7. QFile *localFile;   //本地文件  
  8. eArray inBlock;   //數據緩沖區 

(3)添加私有槽函數:

  1. private slots:  
  2.     void on_startButton_clicked();  
  3.     void start();   //開始監聽  
  4.     void acceptConnection();  //建立連接  
  5.     void updateServerProgress();  //更新進度條,接收數據  
  6. void displayError(QAbstractSocket::SocketError socketError);  
  7.  //顯示錯誤 

4、更改widget.cpp文件。

(1)在構造函數中添加代碼:

  1. totalBytes = 0;  
  2.     bytesReceived = 0;  
  3.     fileNameSize = 0;  
  4.     connect(&tcpServer,SIGNAL(newConnection()),this,  
  5. SLOT(acceptConnection())); 

//當發現新連接時發出newConnection()信號

(2)實現start()函數。

  1. void Widget::start() //開始監聽  
  2. {  
  3.     ui->startButton->setEnabled(false);  
  4.     bytesReceived =0;  
  5.     if(!tcpServer.listen(QHostAddress::LocalHost,6666))  
  6.     {  
  7.         qDebug() << tcpServer.errorString();  
  8.         close();  
  9.         return;  
  10.     }  
  11.     ui->serverStatusLabel->setText(tr(“監聽”));  

(3)實現接受連接函數。

  1. void Widget::acceptConnection()  //接受連接  
  2. {  
  3.     tcpServertcpServerConnection = tcpServer.nextPendingConnection();  
  4. connect(tcpServerConnection,SIGNAL(readyRead()),this,  
  5. SLOT(updateServerProgress()));  
  6.     connect(tcpServerConnection,  
  7. SIGNAL(error(QAbstractSocket::SocketError)),this,  
  8.             SLOT(displayError(QAbstractSocket::SocketError)));  
  9.     ui->serverStatusLabel->setText(tr(“接受連接”));  
  10.     tcpServer.close();  

(4)實現更新進度條函數。

  1. void Widget::updateServerProgress()  //更新進度條,接收數據  
  2.  
  3. {  
  4.  
  5.    QDataStream in(tcpServerConnection);  
  6.  
  7.    in.setVersion(QDataStream::Qt_4_6);  
  8.  
  9.    if(bytesReceived <= sizeof(qint64)*2)  
  10.  
  11.    { //如果接收到的數據小于16個字節,那么是剛開始接收數據,我們保存到//來的頭文件信息  
  12.  
  13.         if((tcpServerConnection->bytesAvailable() >= sizeof(qint64)*2)  
  14.  
  15.             && (fileNameSize == 0))  
  16.  
  17.         { //接收數據總大小信息和文件名大小信息  
  18.  
  19.             in >> totalBytes >> fileNameSize;  
  20.  
  21.             bytesReceived += sizeof(qint64) * 2;  
  22.  
  23.         }  
  24.  
  25.         if((tcpServerConnection->bytesAvailable() >= fileNameSize)  
  26.  
  27.             && (fileNameSize != 0))  
  28.  
  29.         {  //接收文件名,并建立文件  
  30.  
  31.             in >> fileName;  
  32.  
  33.             ui->serverStatusLabel->setText(tr(“接收文件 %1 …”)  
  34.  
  35.                                            .arg(fileName));  
  36.             bytesReceived += fileNameSize;  
  37.            localFile = new QFile(fileName);  
  38.             if(!localFile->open(QFile::WriteOnly))  
  39.             {  
  40.                 qDebug() << “open file error!”;  
  41.                 return;  
  42.             }  
  43.         }  
  44.         else return;  
  45.    }  
  46.    if(bytesReceived < totalBytes)  
  47.    {  //如果接收的數據小于總數據,那么寫入文件  
  48.        bytesReceived += tcpServerConnection->bytesAvailable();  
  49.        inBlock = tcpServerConnection->readAll();  
  50.        localFile->write(inBlock);  
  51.        inBlock.resize(0);  
  52.    }  
  53.    ui->serverProgressBar->setMaximum(totalBytes);  
  54.    ui->serverProgressBar->setValue(bytesReceived);  
  55.    //更新進度條  
  56.    if(bytesReceived == totalBytes)  
  57.    { //接收數據完成時  
  58.     tcpServerConnection->close();  
  59.     localFile->close();  
  60.     ui->startButton->setEnabled(true);  
  61. ui->serverStatusLabel->setText(tr(“接收文件 %1 成功!”)  
  62. .arg(fileName));  
  63.    }  

(5)錯誤處理函數。

  1. void Widget::displayError(QAbstractSocket::SocketError) //錯誤處理  
  2. {  
  3.     qDebug() << tcpServerConnection->errorString();  
  4.     tcpServerConnection->close();  
  5.     ui->serverProgressBar->reset();  
  6.     ui->serverStatusLabel->setText(tr(“服務端就緒”));  
  7.     ui->startButton->setEnabled(true);  

(6)我們在widget.ui中進入“開始監聽”按鈕的單擊事件槽函數,更改如下。

  1. void Widget::on_startButton_clicked() //開始監聽按鈕  
  2. {  
  3.     start();  

5.我們為了使程序中的中文不顯示亂碼,在main.cpp文件中更改。

添加頭文件:#include <QTextCodec>

在main函數中添加代碼:QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

6.運行程序,并同時運行tcpSender程序,效果如下。

Qt網絡之TCP 下篇 網絡學習基礎

我們先在服務器端按下“開始監聽”按鈕,然后在客戶端輸入主機地址和端口號,然后打開要發送的文件,點擊“發送”按鈕進行發送。

在這兩節里我們介紹了TCP的應用,可以看到服務器端和客戶度端都可以當做發送端或者接收端,而且數據的發送與接收只要使用相對應的協議即可,它是可以根據用戶的需要來進行編程的,沒有固定的格式。

本文章原創于 www.yafeilinux.com 

小結:Qt網絡TCP 下篇 網絡學習基礎的內容介紹完了,希望本文內容對你有所幫助!最后推薦相關的資料:】

http://mobile.51cto.com/symbian-268176.htm       qt網絡
http://mobile.51cto.com/symbian-268170.htm       http 編程
http://mobile.51cto.com/symbian-268167_1.htm     獲取網絡地址

責任編輯:zhaolei 來源: 網絡轉載
相關推薦

2011-06-27 10:15:22

Qt 網絡 TCP

2011-06-27 09:47:43

2011-06-27 09:02:18

Qt UDP 網絡

2011-06-02 10:28:18

2011-06-02 10:28:21

Rsh

2011-06-02 11:34:31

Nbtstat

2011-06-02 14:36:25

Netstat

2011-06-02 11:21:59

Tftp

2011-06-02 14:36:19

Route

2011-06-02 10:28:15

網絡命令Arp

2011-06-02 14:36:22

Runas

2011-06-17 10:19:11

Qt QWidge QSetting

2011-06-17 09:58:26

Qt Chapter QObject

2011-06-10 12:17:52

Qt 網絡

2011-06-10 12:44:09

2020-07-28 08:38:10

TCPUDP協議

2011-06-30 16:08:05

Qt 字庫 QPF

2011-06-02 10:28:11

網絡命令

2011-06-22 14:47:51

QT 多線程 QObject

2015-05-28 10:47:38

Unix網絡編程TCP
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久无毛 | 欧美一级全黄 | 九九视频在线观看视频6 | 91视频进入| 九九热这里只有精品在线观看 | 国产成人福利 | 91精品国产色综合久久 | 欧美嘿咻 | 99精品欧美一区二区三区 | 亚洲性视频 | 精品网站999www | 福利电影在线 | 中文在线a在线 | 久久免费精品视频 | 97热在线| 欧美精品在线一区二区三区 | av中文字幕在线 | 波多野结衣精品在线 | 日韩电影中文字幕 | 精品成人免费一区二区在线播放 | 国产精品美女一区二区三区 | 国产精品视频在线播放 | 国产91精品久久久久久久网曝门 | 日韩欧美大片 | 久久精品国产久精国产 | 欧美综合国产精品久久丁香 | 国产精品久久久久久高潮 | 国产高清视频一区二区 | 青青草网站在线观看 | 精品综合视频 | 亚洲高清免费观看 | av天天干 | 综合国产第二页 | 97超碰人人 | 国产在线精品一区 | 91精品国产欧美一区二区成人 | 国产精品久久久久久久久久久久 | 精品影院 | 97精品国产97久久久久久免费 | 亚洲一区电影 | 亚洲一区中文 |