自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例

移動(dòng)開(kāi)發(fā)
TCP協(xié)議的程序使用的是客戶(hù)端/服務(wù)器模式,在Qt中提供了QTcpSocket類(lèi)來(lái)編寫(xiě)客戶(hù)端程序,使用QTcpServer類(lèi)編寫(xiě)服務(wù)器端程序。

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例是本文要介紹的內(nèi)容。TCP即Transmission Control Protocol,傳輸控制協(xié)議。與UDP不同,它是面向連接和數(shù)據(jù)流的可靠傳輸協(xié)議。也就是說(shuō),它能使一臺(tái)計(jì)算機(jī)上的數(shù)據(jù)無(wú)差錯(cuò)的發(fā)往網(wǎng)絡(luò)上的其他計(jì)算機(jī),所以當(dāng)要傳輸大量數(shù)據(jù)時(shí),我們選用TCP協(xié)議。

TCP協(xié)議的程序使用的是客戶(hù)端/服務(wù)器模式,在Qt中提供了QTcpSocket類(lèi)來(lái)編寫(xiě)客戶(hù)端程序,使用QTcpServer類(lèi)編寫(xiě)服務(wù)器端程序。我們?cè)诜?wù)器端進(jìn)行端口的監(jiān)聽(tīng),一旦發(fā)現(xiàn)客戶(hù)端的連接請(qǐng)求,就會(huì)發(fā)出newConnection()信號(hào),我們可以關(guān)聯(lián)這個(gè)信號(hào)到我們自己的槽函數(shù),進(jìn)行數(shù)據(jù)的發(fā)送。而在客戶(hù)端,一旦有數(shù)據(jù)到來(lái)就會(huì)發(fā)出readyRead()信號(hào),我們可以關(guān)聯(lián)此信號(hào),進(jìn)行數(shù)據(jù)的接收。其實(shí),在程序中最難理解的地方就是程序的發(fā)送和接收了,為了讓大家更好的理解,我們?cè)谶@一節(jié)只是講述一個(gè)傳輸簡(jiǎn)單的字符串的例子,在下一節(jié)再進(jìn)行擴(kuò)展,實(shí)現(xiàn)任意文件的傳輸。

一、服務(wù)器端。

在服務(wù)器端的程序中,我們監(jiān)聽(tīng)本地主機(jī)的一個(gè)端口,這里使用6666,然后我們關(guān)聯(lián)newConnection()信號(hào)與自己寫(xiě)的sendMessage()槽函數(shù)。就是說(shuō)一旦有客戶(hù)端的連接請(qǐng)求,就會(huì)執(zhí)行sendMessage()函數(shù),在這個(gè)函數(shù)里我們發(fā)送一個(gè)簡(jiǎn)單的字符串。

1.我們新建Qt4 Gui Application,工程名為“tcpServer”,選中QtNetwork模塊,Base class選擇QWidget。(說(shuō)明:如果一些Qt Creator版本沒(méi)有添加模塊一項(xiàng),我們就需要在工程文件tcpServer.pro中添加一行代碼:QT += network)

2.我們?cè)趙idget.ui的設(shè)計(jì)區(qū)添加一個(gè)Label,更改其objectName為statusLabel,用于顯示一些狀態(tài)信息。如下:

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例


 
3.在widget.h文件中做以下更改。

添加頭文件:#include <QtNetWork>

添加private對(duì)象:QTcpServer *tcpServer;

添加私有槽函數(shù):

  1. private slots:  
  2. void sendMessage(); 

4.在widget.cpp文件中進(jìn)行更改。在其構(gòu)造函數(shù)中添加代碼:

  1. tcpServer = new QTcpServer(this);  
  2.     if(!tcpServer->listen(QHostAddress::LocalHost,6666))  
  3.     {  //監(jiān)聽(tīng)本地主機(jī)的6666端口,如果出錯(cuò)就輸出錯(cuò)誤信息,并關(guān)閉  
  4.         qDebug() << tcpServer->errorString();  
  5.         close();  
  6.     }  
  7.  connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage()));  
  8. //連接信號(hào)和相應(yīng)槽函數(shù) 

我們?cè)跇?gòu)造函數(shù)中使用tcpServer的listen()函數(shù)進(jìn)行監(jiān)聽(tīng),然后關(guān)聯(lián)了newConnection()和我們自己的sendMessage()函數(shù)。下面我們實(shí)現(xiàn)sendMessage()函數(shù)。

  1. void Widget::sendMessage()  
  2. {  
  3.     QByteArray block; //用于暫存我們要發(fā)送的數(shù)據(jù)  
  4.     QDataStream out(&block,QIODevice::WriteOnly);  
  5.     //使用數(shù)據(jù)流寫(xiě)入數(shù)據(jù)  
  6.     out.setVersion(QDataStream::Qt_4_6);  
  7.     //設(shè)置數(shù)據(jù)流的版本,客戶(hù)端和服務(wù)器端使用的版本要相同  
  8.     out<<(quint16) 0;  
  9.     out<<tr(“hello Tcp!!!”);  
  10.     out.device()->seek(0);  
  11.     out<<(quint16) (block.size() – sizeof(quint16));  
  12.     QTcpSocket *clientConnection = tcpServer->nextPendingConnection();  
  13.     //我們獲取已經(jīng)建立的連接的子套接字  
  14.     connect(clientConnection,SIGNAL(disconnected()),clientConnection,  
  15.             SLOT(deleteLater()));  
  16.     clientConnection->write(block);  
  17.     clientConnection->disconnectFromHost();  
  18.     ui->statusLabel->setText(“send message successful!!!”);  
  19.     //發(fā)送數(shù)據(jù)成功后,顯示提示  

這個(gè)是數(shù)據(jù)發(fā)送函數(shù),我們主要介紹兩點(diǎn):

(1)為了保證在客戶(hù)端能接收到完整的文件,我們都在數(shù)據(jù)流的最開(kāi)始寫(xiě)入完整文件的大小信息,這樣客戶(hù)端就可以根據(jù)大小信息來(lái)判斷是否接受到了完整的文件。而在服務(wù)器端,我們?cè)诎l(fā)送數(shù)據(jù)時(shí)就要首先發(fā)送實(shí)際文件的大小信息,但是,文件的大小一開(kāi)始是無(wú)法預(yù)知的,所以我們先使用了out<<(quint16) 0;在block的開(kāi)始添加了一個(gè)quint16大小的空間,也就是兩字節(jié)的空間,它用于后面放置文件的大小信息。然后out<<tr(“hello Tcp!!!”);輸入實(shí)際的文件,這里是字符串。當(dāng)文件輸入完成后我們?cè)谑褂胦ut.device()->seek(0);返回到block的開(kāi)始,加入實(shí)際的文件大小信息,也就是后面的代碼,它是實(shí)際文件的大小:out<<(quint16) (block.size() – sizeof(quint16));

(2)在服務(wù)器端我們可以使用tcpServer的nextPendingConnection()函數(shù)來(lái)獲取已經(jīng)建立的連接的Tcp套接字,使用它來(lái)完成數(shù)據(jù)的發(fā)送和其它操作。比如這里,我們關(guān)聯(lián)了disconnected()信號(hào)和deleteLater()槽函數(shù),然后我們發(fā)送數(shù)據(jù)

  1. clientConnection->write(block); 

然后是clientConnection->disconnectFromHost();它表示當(dāng)發(fā)送完成時(shí)就會(huì)斷開(kāi)連接,這時(shí)就會(huì)發(fā)出disconnected()信號(hào),而最后調(diào)用deleteLater()函數(shù)保證在關(guān)閉連接后刪除該套接字clientConnection。

5.這樣服務(wù)器的程序就完成了,我們先運(yùn)行一下程序。

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例

 

 

 

#p#
 
二、客戶(hù)端。

我們?cè)诳蛻?hù)端程序中向服務(wù)器發(fā)送連接請(qǐng)求,當(dāng)連接成功時(shí)接收服務(wù)器發(fā)送的數(shù)據(jù)。

1.我們新建Qt4 Gui Application,工程名為“tcpClient”,選中QtNetwork模塊,Base class選擇QWidget。

2,我們?cè)趙idget.ui中添加幾個(gè)標(biāo)簽Label和兩個(gè)Line Edit以及一個(gè)按鈕Push Button。

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例
 
其中“主機(jī)”后的Line Edit的objectName為hostLineEdit,“端口號(hào)”后的為portLineEdit。“收到的信息”標(biāo)簽的objectName為messageLabel 。

3.在widget.h文件中做更改。

添加頭文件:#include <QtNetwork>

添加private變量:

  1. QTcpSocket *tcpSocket;  
  2. QString message;  //存放從服務(wù)器接收到的字符串  
  3. quint16 blockSize;  //存放文件的大小信息 

添加私有槽函數(shù):

  1. private slots:  
  2.     void newConnect(); //連接服務(wù)器  
  3.     void readMessage();  //接收數(shù)據(jù)  
  4. void displayError(QAbstractSocket::SocketError);  //顯示錯(cuò)誤 

4.在widget.cpp文件中做更改。

(1)在構(gòu)造函數(shù)中添加代碼:

  1. tcpSocket = new QTcpSocket(this);  
  2. connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));  
  3. connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),  
  4.          this,SLOT(displayError(QAbstractSocket::SocketError))); 

這里關(guān)聯(lián)了tcpSocket的兩個(gè)信號(hào),當(dāng)有數(shù)據(jù)到來(lái)時(shí)發(fā)出readyRead()信號(hào),我們執(zhí)行讀取數(shù)據(jù)的readMessage()函數(shù)。當(dāng)出現(xiàn)錯(cuò)誤時(shí)發(fā)出error()信號(hào),我們執(zhí)行displayError()槽函數(shù)。

(2)實(shí)現(xiàn)newConnect()函數(shù)。

  1. void Widget::newConnect()  
  2. {  
  3.     blockSize = 0; //初始化其為0  
  4.     tcpSocket->abort(); //取消已有的連接  
  5.     tcpSocket->connectToHost(ui->hostLineEdit->text(),  
  6.                              ui->portLineEdit->text().toInt());  
  7.     //連接到主機(jī),這里從界面獲取主機(jī)地址和端口號(hào)  

這個(gè)函數(shù)實(shí)現(xiàn)了連接到服務(wù)器,下面會(huì)在“連接”按鈕的單擊事件槽函數(shù)中調(diào)用這個(gè)函數(shù)。

(3)實(shí)現(xiàn)readMessage()函數(shù)。

  1. void Widget::readMessage()  
  2. {  
  3.     QDataStream in(tcpSocket);  
  4.     in.setVersion(QDataStream::Qt_4_6);  
  5.     //設(shè)置數(shù)據(jù)流版本,這里要和服務(wù)器端相同  
  6.     if(blockSize==0) //如果是剛開(kāi)始接收數(shù)據(jù)  
  7.     {  
  8.         //判斷接收的數(shù)據(jù)是否有兩字節(jié),也就是文件的大小信息  
  9.         //如果有則保存到blockSize變量中,沒(méi)有則返回,繼續(xù)接收數(shù)據(jù)  
  10.         if(tcpSocket->bytesAvailable() < (int)sizeof(quint16)) return;  
  11.         in >> blockSize;  
  12.     }  
  13.     if(tcpSocket->bytesAvailable() < blockSize) return;  
  14.     //如果沒(méi)有得到全部的數(shù)據(jù),則返回,繼續(xù)接收數(shù)據(jù)  
  15.     in >> message;  
  16.     //將接收到的數(shù)據(jù)存放到變量中  
  17.     ui->messageLabel->setText(message);  
  18.     //顯示接收到的數(shù)據(jù)  

這個(gè)函數(shù)實(shí)現(xiàn)了數(shù)據(jù)的接收,它與服務(wù)器端的發(fā)送函數(shù)相對(duì)應(yīng)。首先我們要獲取文件的大小信息,

  1. void Widget::displayError(QAbstractSocket::SocketError)  
  2. {  
  3.     qDebug() << tcpSocket->errorString(); //輸出錯(cuò)誤信息  

然后根據(jù)文件的大小來(lái)判斷是否接收到了完整的文件。

(4)實(shí)現(xiàn)displayError()函數(shù)。

這里簡(jiǎn)單的實(shí)現(xiàn)了錯(cuò)誤信息的輸出。

(5)我們?cè)趙idget.ui中進(jìn)入“連接”按鈕的單擊事件槽函數(shù),然后更改如下。

  1. void Widget::on_pushButton_clicked() //連接按鈕  
  2. {  
  3.     newConnect(); //請(qǐng)求連接  

這里直接調(diào)用了newConnect()函數(shù)。

5.我們運(yùn)行程序,同時(shí)運(yùn)行服務(wù)器程序,然后在“主機(jī)”后填入“localhost”,在“端口號(hào)”后填入“6666”,點(diǎn)擊“連接”按鈕,效果如下。

Qt TCP協(xié)議 傳輸簡(jiǎn)單字符串實(shí)例
 
可以看到我們正確地接收到了數(shù)據(jù)。因?yàn)榉?wù)器端和客戶(hù)端是在同一臺(tái)機(jī)子上運(yùn)行的,所以我這里填寫(xiě)了“主機(jī)”為“localhost”,如果你在不同的機(jī)子上運(yùn)行,需要在“主機(jī)”后填寫(xiě)其正確的IP地址。

小結(jié):Qt TCP協(xié)議傳輸簡(jiǎn)單字符串實(shí)例,到這里我們最簡(jiǎn)單的TCP應(yīng)用程序就完成了,在下一節(jié)我們將會(huì)對(duì)它進(jìn)行擴(kuò)展,實(shí)現(xiàn)任意文件的傳輸。

責(zé)任編輯:zhaolei 來(lái)源: 互聯(lián)網(wǎng)
相關(guān)推薦

2010-06-17 17:48:05

TCP傳輸控制協(xié)議

2023-02-09 08:43:11

SwiftGo字符串

2010-06-09 16:28:50

TCP IP傳輸協(xié)議

2010-06-09 13:54:13

TCP傳輸協(xié)議

2009-08-26 13:24:54

C#字符串

2013-05-27 10:48:16

TCPUDP傳輸協(xié)議

2010-06-17 23:21:16

TCP傳輸控制協(xié)議

2010-06-13 15:32:57

TCP協(xié)議

2010-06-09 13:21:30

TCP傳輸層協(xié)議

2010-03-03 09:12:25

.NET字符串拘留池

2010-06-13 14:49:40

TCP IP協(xié)議優(yōu)化

2010-09-13 15:06:40

sql server字

2011-06-16 17:01:21

Qt MeeGo 排序

2021-10-11 10:41:14

TCP傳輸層協(xié)議網(wǎng)絡(luò)

2009-09-01 17:41:53

C#截取字符串函數(shù)

2020-05-13 12:17:33

RedisC字符C語(yǔ)言

2009-08-21 14:25:23

C#異步傳輸字符串

2009-08-21 14:33:15

C#異步傳輸字符串

2020-08-31 19:19:27

TCPUDP視屏面試

2025-04-27 10:02:50

JavaScript前端開(kāi)發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)