版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第10章 Qt 5網(wǎng)絡(luò)與通信獲取本機(jī)網(wǎng)絡(luò)信息第1頁(yè),共80頁(yè)?!纠浚ê?jiǎn)單)(CH1001)獲得本機(jī)網(wǎng)絡(luò)信息。實(shí)現(xiàn)步驟如下。(1)頭文件“networkinformation.h”的具體代碼如下:#include #include #include #include #include #include class NetworkInformation : public QWidget Q_OBJECTpublic: NetworkInformation(QWidget *parent = 0); NetworkInformation();private: QLabel *hostLabel;
2、QLineEdit *LineEditLocalHostName; QLabel *ipLabel; QLineEdit *LineEditAddress; QPushButton *detailBtn; QGridLayout *mainLayout;獲取本機(jī)網(wǎng)絡(luò)信息第2頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息(2)源文件“networkinformation.cpp”的具體代碼如下:#include networkinformation.hNetworkInformation:NetworkInformation(QWidget *parent) : QWidget(parent) hostLabe
3、l = new QLabel(tr(主機(jī)名:); LineEditLocalHostName = new QLineEdit; ipLabel = new QLabel(tr(IP 地址:); LineEditAddress = new QLineEdit; detailBtn = new QPushButton(tr(詳細(xì)); mainLayout = new QGridLayout(this); mainLayout-addWidget(hostLabel,0,0); mainLayout-addWidget(LineEditLocalHostName,0,1); mainLayout-a
4、ddWidget(ipLabel,1,0); mainLayout-addWidget(LineEditAddress,1,1); mainLayout-addWidget(detailBtn,2,0,1,2);第3頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息此時(shí),運(yùn)行結(jié)果如圖10.1所示。第4頁(yè),共80頁(yè)。#include #include public: void getHostInformation();public slots: void slotDetail();獲取本機(jī)網(wǎng)絡(luò)信息以上步驟完成了界面,下面開(kāi)始真正實(shí)現(xiàn)獲取本機(jī)網(wǎng)絡(luò)信息的內(nèi)容。(1)在文件“NetworkI”中添加如下代碼: QT +=
5、 network(2)在頭文件“networkinformation.h”中添加如下代碼:第5頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息(3)在源文件“networkinformation.cpp”中添加代碼。其中,在構(gòu)造函數(shù)的最后添加:getHostInformation();connect(detailBtn,SIGNAL(clicked(),this,SLOT(slotDetail();getHostInformation()函數(shù)用于獲取主機(jī)信息。具體實(shí)現(xiàn)代碼如下:void NetworkInformation:getHostInformation() QString localHostName =
6、 QHostInfo:localHostName();/(a) LineEditLocalHostName-setText(localHostName); QHostInfo hostInfo = QHostInfo:fromName(localHostName);/(b)/獲取主機(jī)的IP地址列表 QList listAddress = hostInfo.addresses(); if(!listAddress.isEmpty()/(c) LineEditAddress-setText(listAddress.at(2).toString(); 第6頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息其中,(a)
7、QString localHostName = QHostInfo:localHostName():獲取本機(jī)主機(jī)名。QHostInfo提供了一系列有關(guān)網(wǎng)絡(luò)信息的靜態(tài)函數(shù),可以根據(jù)主機(jī)名獲取分配的IP地址,也可以根據(jù)IP地址獲取相應(yīng)的主機(jī)名。(b) QHostInfo hostInfo = QHostInfo:fromName(localHostName):根據(jù)主機(jī)名獲取相關(guān)主機(jī)信息,包括IP地址等。QHostInfo:fromName()函數(shù)通過(guò)主機(jī)名查找IP地址信息。(c) if(!listAddress.isEmpty():獲取的主機(jī)IP地址列表可能為空。在不為空的情況下使用第一個(gè)IP地址
8、。第7頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息slotDetail()函數(shù)獲取與網(wǎng)絡(luò)接口相關(guān)的信息,具體實(shí)現(xiàn)代碼如下:void NetworkInformation:slotDetail() QString detail=; QList list=QNetworkInterface:allInterfaces();/(a) for(int i=0;ilist.count();i+) QNetworkInterface interface=list.at(i); detail=detail+tr(設(shè)備:)+()+n;/(b) detail=detail+tr(硬件地址:)+interface.hardwa
9、reAddress()+n;/(c) QList entryList=interface.addressEntries();/(d) for(int j=1;jentryList.count();j+) QNetworkAddressEntry entry=entryList.at(j); detail=detail+t+tr(IP 地址:)+entry.ip().toString()+n; detail=detail+t+tr(子網(wǎng)掩碼:)+mask().toString() +n; detail=detail+t+tr(廣播地址:)+entry.broadcast().toString()
10、 +n; QMessageBox:information(this,tr(Detail),detail);第8頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息其中,(a)QList list=QNetworkInterface:allInterfaces():QNetwork Interface 類提供了一個(gè)主機(jī)IP地址和網(wǎng)絡(luò)接口的列表。(b) ():獲取網(wǎng)絡(luò)接口的名稱。(c) interface.hardwareAddress():獲取網(wǎng)絡(luò)接口的硬件地址。(d) interface.addressEntries():每個(gè)網(wǎng)絡(luò)接口包括0個(gè)或多個(gè)IP地址,每個(gè)IP地址有選擇性地與一個(gè)子網(wǎng)掩碼和(或)一個(gè)廣播地址相
11、關(guān)聯(lián)。QNetworkAddressEntry類存儲(chǔ)了被網(wǎng)絡(luò)接口支持的一個(gè)IP地址,同時(shí)還包括與之相關(guān)的子網(wǎng)掩碼和廣播地址。第9頁(yè),共80頁(yè)。獲取本機(jī)網(wǎng)絡(luò)信息(4)運(yùn)行結(jié)果如圖10.2所示。單擊“詳細(xì)”按鈕后,彈出如圖10.3所示的信息窗口。 第10頁(yè),共80頁(yè)。第10章 Qt 5網(wǎng)絡(luò)與通信基于UDP的網(wǎng)絡(luò)廣播程序第11頁(yè),共80頁(yè)?;赨DP的網(wǎng)絡(luò)廣播程序用戶數(shù)據(jù)報(bào)協(xié)議(User Data Protocol,UDP)是一種簡(jiǎn)單輕量級(jí)、不可靠、面向數(shù)據(jù)報(bào)、無(wú)連接的傳輸層協(xié)議,可以應(yīng)用在可靠性不是十分重要的場(chǎng)合,如短消息、廣播信息等。適合應(yīng)用的情況有以下幾種: 網(wǎng)絡(luò)數(shù)據(jù)大多為短消息。 擁有大量客
12、戶端。 對(duì)數(shù)據(jù)安全性無(wú)特殊要求。 網(wǎng)絡(luò)負(fù)擔(dān)非常重,但對(duì)響應(yīng)速度要求高。第12頁(yè),共80頁(yè)。01UDP工作原理第13頁(yè),共80頁(yè)。UDP工作原理如圖10.4所示,UDP客戶端向UDP服務(wù)器發(fā)送一定長(zhǎng)度的請(qǐng)求報(bào)文,報(bào)文大小的限制與各系統(tǒng)的協(xié)議實(shí)現(xiàn)有關(guān),但不得超過(guò)其下層IP規(guī)定的64KB;UDP服務(wù)器同樣以報(bào)文形式做出響應(yīng)。如果服務(wù)器未收到此請(qǐng)求,客戶端不會(huì)進(jìn)行重發(fā),因此報(bào)文的傳輸是不可靠的。第14頁(yè),共80頁(yè)。02UDP 編程模型第15頁(yè),共80頁(yè)。UDP 編程模型下面介紹基于UDP的經(jīng)典編程模型,UDP客戶端與服務(wù)器間的交互時(shí)序如圖10.5所示??梢钥闯?,在UDP方式下,客戶端并不與服務(wù)器建立連
13、接,它只負(fù)責(zé)調(diào)用發(fā)送函數(shù)向服務(wù)器發(fā)出數(shù)據(jù)報(bào)。類似地,服務(wù)器也不從客戶端接收連接,只負(fù)責(zé)調(diào)用接收函數(shù),等待來(lái)自某客戶端的數(shù)據(jù)到達(dá)。第16頁(yè),共80頁(yè)。03“實(shí)例”UDP服務(wù)器編程第17頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程【例】(簡(jiǎn)單)(CH1002)服務(wù)器端的編程。(1)在頭文件“udpserver.h”中聲明了需要的各種控件,其具體代碼如下:#include #include #include #include #include class UdpServer : public QDialog Q_OBJECTpublic: UdpServer(QWidget *parent=0,Qt:Wi
14、ndowFlags f=0); UdpServer();private: QLabel *TimerLabel; QLineEdit *TextLineEdit; QPushButton *StartBtn; QVBoxLayout *mainLayout;第18頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程(2)源文件“udpserver.cpp”的具體代碼如下:#include udpserver.hUdpServer:UdpServer(QWidget *parent,Qt:WindowFlags f) : QDialog(parent,f) setWindowTitle(tr(UDP Serv
15、er);/設(shè)置窗體的標(biāo)題/* 初始化各個(gè)控件 */ TimerLabel = new QLabel(tr(計(jì)時(shí)器:),this); TextLineEdit = new QLineEdit(this); StartBtn = new QPushButton(tr(開(kāi)始),this);/* 設(shè)置布局 */ mainLayout = new QVBoxLayout(this); mainLayout-addWidget(TimerLabel); mainLayout-addWidget(TextLineEdit); mainLayout-addWidget(StartBtn);第19頁(yè),共80頁(yè)。
16、“實(shí)例”UDP服務(wù)器編程(3)服務(wù)器界面如圖10.6所示。第20頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程具體操作步驟如下。(1)在“UdpS”中添加如下語(yǔ)句: QT += network(2)在頭文件“udpserver.h”中添加需要的槽函數(shù),其具體代碼如下:#include #include public slots: void StartBtnClicked(); void timeout();private:int port; bool isStarted; QUdpSocket *udpSocket; QTimer *timer;第21頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程(3)在源文
17、件“udpserver.cpp”中添加聲明: #include 其中,在構(gòu)造函數(shù)中添加如下代碼:connect(StartBtn,SIGNAL(clicked(),this,SLOT(StartBtnClicked();port = 5555;/設(shè)置UDP的端口號(hào)參數(shù),服務(wù)器定時(shí)向此端口發(fā)送廣播信息isStarted = false;udpSocket = new QUdpSocket(this);timer = new QTimer(this);/創(chuàng)建一個(gè)QUdpSocket/定時(shí)發(fā)送廣播信息connect(timer,SIGNAL(timeout(),this,SLOT(timeout()
18、;第22頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程StartBtnClicked()函數(shù)的具體代碼如下:void UdpServer:StartBtnClicked() if(!isStarted) StartBtn-setText(tr(停止); timer-start(1000); isStarted =true; else StartBtn-setText(tr(開(kāi)始); isStarted = false; timer-stop(); 第23頁(yè),共80頁(yè)?!皩?shí)例”UDP服務(wù)器編程timeout()函數(shù)完成了向端口發(fā)送廣播信息的功能,其具體代碼如下:void UdpServer:timeou
19、t() QString msg = TextLineEdit-text(); int length=0; if(msg=) return; if(length=udpSocket-writeDatagram(msg.toLatin1(), msg.length(),QHostAddress:Broadcast,port)!=msg.length() return; 第24頁(yè),共80頁(yè)。04“實(shí)例”UDP客戶端編程第25頁(yè),共80頁(yè)?!皩?shí)例”UDP客戶端編程【例】(簡(jiǎn)單)(CH1003)客戶端的編程。(1)在頭文件“udpclient.h”中聲明了需要的各種控件,其具體代碼如下:#include
20、 #include #include #include class UdpClient : public QDialog Q_OBJECTpublic: UdpClient(QWidget *parent = 0,Qt:WindowFlags f=0); UdpClient();private: QTextEdit *ReceiveTextEdit; QPushButton *CloseBtn; QVBoxLayout *mainLayout;第26頁(yè),共80頁(yè)?!皩?shí)例”UDP客戶端編程(2)源文件“udpclient.cpp”的具體代碼如下:#include udpclient.hUdpCl
21、ient:UdpClient(QWidget *parent, Qt:WindowFlags f) : QDialog(parent,f) setWindowTitle(tr(UDP Client);/設(shè)置窗體的標(biāo)題/* 初始化各個(gè)控件 */ ReceiveTextEdit = new QTextEdit(this); CloseBtn = new QPushButton(tr(Close),this);/* 設(shè)置布局 */ mainLayout=new QVBoxLayout(this); mainLayout-addWidget(ReceiveTextEdit); mainLayout-a
22、ddWidget(CloseBtn);第27頁(yè),共80頁(yè)?!皩?shí)例”UDP客戶端編程(3)客戶端界面如圖10.7所示。第28頁(yè),共80頁(yè)?!皩?shí)例”UDP客戶端編程以上只是完成了客戶端界面的實(shí)現(xiàn),下面完成它的數(shù)據(jù)接收和顯示的功能。操作步驟如下。(1)在“UdpC”中添加如下語(yǔ)句: QT += network(2)在頭文件“udpclient.h”中添加如下代碼:#include public slots: void CloseBtnClicked(); void dataReceived();private:int port; QUdpSocket *udpSocket;第29頁(yè),共80頁(yè)?!皩?shí)例
23、”UDP客戶端編程(3)在源文件“udpclient.cpp”中添加如下聲明:#include #include 其中,在構(gòu)造函數(shù)中添加的代碼如下:connect(CloseBtn,SIGNAL(clicked(),this,SLOT(CloseBtnClicked();port =5555;/設(shè)置UDP的端口號(hào)參數(shù),指定在此端口上監(jiān)聽(tīng)數(shù)據(jù)udpSocket = new QUdpSocket(this);/創(chuàng)建一個(gè)QUdpSocketconnect(udpSocket,SIGNAL(readyRead(),this,SLOT(dataReceived();/(a)bool result=udp
24、Socket-bind(port);/綁定到指定的端口上if(!result) QMessageBox:information(this,tr(error),tr(udp socket create error!); return;CloseBtnClicked()函數(shù)的具體內(nèi)容如下:void UdpClient:CloseBtnClicked() close();第30頁(yè),共80頁(yè)。“實(shí)例”UDP客戶端編程dataReceived()函數(shù)響應(yīng)QUdpSocket的readyRead()信號(hào),一旦UdpSocket對(duì)象中有數(shù)據(jù)可讀時(shí),即通過(guò)readDatagram()方法將數(shù)據(jù)讀出并顯示。其具
25、體代碼如下:void UdpClient:dataReceived() while(udpSocket-hasPendingDatagrams()/(a) QByteArray datagram; datagram.resize(udpSocket-pendingDatagramSize(); udpSocket-readDatagram(datagram.data(),datagram.size();/(b) QString msg=datagram.data(); ReceiveTextEdit-insertPlainText(msg);/顯示數(shù)據(jù)內(nèi)容 第31頁(yè),共80頁(yè)?!皩?shí)例”UDP客
26、戶端編程同時(shí)運(yùn)行UdpServer與UdpClient工程,首先在服務(wù)器界面的文本框中輸入“hello!”,然后單擊“開(kāi)始”按鈕,按鈕文本變?yōu)椤巴V埂?,客戶端就開(kāi)始不斷地收到“hello!”字符消息并顯示在文本區(qū),當(dāng)單擊服務(wù)器的“停止”按鈕后,按鈕文本又變回“開(kāi)始”,客戶端也就停止了字符的顯示,再次單擊服務(wù)器的“開(kāi)始”按鈕,客戶端又繼續(xù)接收并顯示如此循環(huán)往復(fù),效果如圖10.8所示。第32頁(yè),共80頁(yè)。第10章 Qt 5網(wǎng)絡(luò)與通信基于TCP的網(wǎng)絡(luò)聊天室程序第33頁(yè),共80頁(yè)。基于TCP的網(wǎng)絡(luò)聊天室程序TCP與UDP的差別見(jiàn)表10.1。比 較 項(xiàng)TCPUDP是否連接面向連接無(wú)連接傳輸可靠性可靠不可
27、靠流量控制提供不提供工作方式全雙工可以是全雙工應(yīng)用場(chǎng)合大量數(shù)據(jù)少量數(shù)據(jù)速度慢快第34頁(yè),共80頁(yè)。01TCP工作原理第35頁(yè),共80頁(yè)。 TCP工作原理如圖10.9所示,TCP能夠?yàn)閼?yīng)用程序提供可靠的通信連接,使一臺(tái)計(jì)算機(jī)發(fā)出的字節(jié)流無(wú)差錯(cuò)地送達(dá)網(wǎng)絡(luò)上的其他計(jì)算機(jī)。因此,對(duì)可靠性要求高的數(shù)據(jù)通信系統(tǒng)往往使用TCP傳輸數(shù)據(jù),但在正式收發(fā)數(shù)據(jù)前,通信雙方必須首先建立連接。第36頁(yè),共80頁(yè)。02TCP編程模型第37頁(yè),共80頁(yè)。TCP編程模型下面介紹基于TCP的經(jīng)典編程模型,TCP客戶端與服務(wù)器間的交互時(shí)序如圖10.10所示。第38頁(yè),共80頁(yè)。03“實(shí)例”TCP服務(wù)器端編程第39頁(yè),共80頁(yè)?!?/p>
28、實(shí)例”TCP服務(wù)器端編程【例】(難度中等)(CH1004)TCP服務(wù)器端的編程。建立工程TcpS,文件代碼如下。(1)頭文件“tcpserver.h”中聲明了需要的各種控件,TcpServer繼承自QDialog,實(shí)現(xiàn)了服務(wù)器端的對(duì)話框顯示與控制。其具體代碼如下:#include #include #include #include #include #include class TcpServer : public QDialog Q_OBJECTpublic: TcpServer(QWidget *parent = 0,Qt:WindowFlags f=0); TcpServer();pr
29、ivate: QListWidget *ContentListWidget; QLabel *PortLabel; QLineEdit *PortLineEdit; QPushButton *CreateBtn; QGridLayout *mainLayout;第40頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(2)在源文件“tcpserver.cpp”中,TcpServer類的構(gòu)造函數(shù)主要實(shí)現(xiàn)窗體各控件的創(chuàng)建、布局等,其具體代碼如下:#include tcpserver.hTcpServer:TcpServer(QWidget *parent,Qt:WindowFlags f) : QDialo
30、g(parent,f) setWindowTitle(tr(TCP Server); ContentListWidget = new QListWidget; PortLabel = new QLabel(tr(端口:); PortLineEdit = new QLineEdit; CreateBtn = new QPushButton(tr(創(chuàng)建聊天室); mainLayout = new QGridLayout(this); mainLayout-addWidget(ContentListWidget,0,0,1,2); mainLayout-addWidget(PortLabel,1,0
31、); mainLayout-addWidget(PortLineEdit,1,1); mainLayout-addWidget(CreateBtn,2,0,1,2);第41頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(3)服務(wù)器端界面如圖10.11所示。第42頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程以上完成了服務(wù)器端界面的設(shè)計(jì),下面將詳細(xì)完成聊天室的服務(wù)器端功能。(1)在工程文件“TcpS”中添加如下語(yǔ)句: QT += network(2)在工程“TcpS”中添加C+類文件“tcpclientsocket.h”及“tcpclientsocket.cpp”,TcpClientSocket繼承自QTc
32、pSocket,創(chuàng)建一個(gè)TCP套接字,以便在服務(wù)器端實(shí)現(xiàn)與客戶端程序的通信。頭文件“tcpclientsocket.h”的具體代碼如下:#include #include class TcpClientSocket : public QTcpSocket Q_OBJECT /添加宏(Q_OBJECT)是為了實(shí)現(xiàn)信號(hào)與槽的通信public: TcpClientSocket(QObject *parent=0);signals: void updateClients(QString,int); void disconnected(int);protected slots: void dataRec
33、eived(); void slotDisconnected();第43頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(3)在源文件“tcpclientsocket.cpp”中,構(gòu)造函數(shù)(TcpClientSocket)的內(nèi)容(指定了信號(hào)與槽的連接關(guān)系)如下:#include tcpclientsocket.hTcpClientSocket:TcpClientSocket(QObject *parent) connect(this,SIGNAL(readyRead(),this,SLOT(dataReceived();/(a)connect(this,SIGNAL(disconnected(),th
34、is,SLOT(slotDisconnected();/(b)其中,(a) connect(this,SIGNAL(readyRead(),this,SLOT(dataReceived():readyRead()是QIODevice的signal,由QTcpSocket繼承而來(lái)。QIODevice是所有輸入/輸出設(shè)備的一個(gè)抽象類,其中定義了基本的接口,在Qt中,QTcpSocket也被看成一個(gè)QIODevice,readyRead()信號(hào)在有數(shù)據(jù)到來(lái)時(shí)發(fā)出。(b) connect(this,SIGNAL(disconnected(),this,SLOT(slotDisconnected():d
35、isconnected()信號(hào)在斷開(kāi)連接時(shí)發(fā)出。第44頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程在源文件“tcpclientsocket.cpp”中,dataReceived()函數(shù)的具體代碼如下:void TcpClientSocket:dataReceived() while(bytesAvailable()0) int length = bytesAvailable(); char buf1024; read(buf,length); QString msg=buf; emit updateClients(msg,length); 在源文件“tcpclientsocket.cpp”中,槽函
36、數(shù)slotDisconnected()的具體代碼如下:void TcpClientSocket:slotDisconnected() emit disconnected(this-socketDescriptor();第45頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(4)在工程“TcpS”中添加C+類文件“server.h”及“server.cpp”,Server繼承自QTcpServer,實(shí)現(xiàn)一個(gè)TCP協(xié)議的服務(wù)器。利用QTcpServer,開(kāi)發(fā)者可以監(jiān)聽(tīng)到指定端口的TCP連接。其具體代碼如下:#include #include #include tcpclientsocket.h/包含TCP
37、的套接字class Server : public QTcpServer Q_OBJECT /添加宏(Q_OBJECT)是為了實(shí)現(xiàn)信號(hào)與槽的通信public: Server(QObject *parent=0,int port=0); QList tcpClientSocketList;signals: void updateServer(QString,int);public slots: void updateClients(QString,int); void slotDisconnected(int);protected: void incomingConnection(int soc
38、ketDescriptor);第46頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(5)在源文件“server.cpp”中,構(gòu)造函數(shù)(Server)的具體內(nèi)容如下:#include server.hServer:Server(QObject *parent,int port):QTcpServer(parent) listen(QHostAddress:Any,port);其中,listen(QHostAddress:Any,port)在指定的端口對(duì)任意地址進(jìn)行監(jiān)聽(tīng)。QHostAddress定義了幾種特殊的IP地址,如QHostAddress:Null表示一個(gè)空地址;QHostAddress:Loc
39、alHost表示IPv4的本機(jī)地址;QHostAddress:LocalHostIPv6表示IPv6的本機(jī)地址;QHostAddress:Broadcast表示廣播地址55;QHostAddress:Any表示IPv4的任意地址;QHostAddress:AnyIPv6表示IPv6的任意地址。第47頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程在源文件“server.cpp”中,當(dāng)出現(xiàn)一個(gè)新的連接時(shí),QTcpSever觸發(fā)incomingConnection()函數(shù),參數(shù)socketDescriptor指定了連接的Socket描述符,其具體代碼如下:void Server:incomingConne
40、ction(int socketDescriptor) TcpClientSocket *tcpClientSocket=new TcpClientSocket(this); /(a) connect(tcpClientSocket,SIGNAL(updateClients(QString,int), this,SLOT(updateClients(QString,int);/(b) connect(tcpClientSocket,SIGNAL(disconnected(int),this, SLOT(slotDisconnected(int);/(c) tcpClientSocket-set
41、SocketDescriptor(socketDescriptor);/(d) tcpClientSocketList.append(tcpClientSocket);/(e)第48頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程其中,(a) TcpClientSocket*tcpClientSocket=newTcpClientSocket(this):創(chuàng)建一個(gè)新的TcpClientSocket與客戶端通信。(b) connect(tcpClientSocket,SIGNAL(updateClients(QString,int),this,SLOT(update Clients (QString,i
42、nt):連接TcpClientSocket的updateClients信號(hào)。(c) connect(tcpClientSocket,SIGNAL(disconnected(int),this,SLOT(slotDisconnected(int):連接TcpClientSocket的disconnected信號(hào)。(d) tcpClientSocket-setSocketDescriptor(socketDescriptor):將新創(chuàng)建的TcpClient Socket的套接字描述符指定為參數(shù)socketDescriptor。(e) tcpClientSocketList.append(tcpCl
43、ientSocket):將tcpClientSocket加入客戶端套接字列表以便管理。第49頁(yè),共80頁(yè)。“實(shí)例”TCP服務(wù)器端編程在源文件“server.cpp”中,updateClients()函數(shù)將任意客戶端發(fā)來(lái)的信息進(jìn)行廣播,保證聊天室的所有成員均能看到其他人的發(fā)言。其具體代碼如下:void Server:updateClients(QString msg,int length) emit updateServer(msg,length);/(a) for(int i=0;iwrite(msg.toLatin1(),length)!=length) continue; 其中,(a) e
44、mit updateServer(msg,length):發(fā)出updateServer信號(hào),用來(lái)通知服務(wù)器對(duì)話框更新相應(yīng)的顯示狀態(tài)。(b) for(int i=0;itcpClientSocketList.count();i+):實(shí)現(xiàn)信息的廣播,tcpClientSocketList中保存了所有與服務(wù)器相連的TcpClientSocket對(duì)象。第50頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程在源文件“server.cpp”中,slotDisconnected()函數(shù)實(shí)現(xiàn)從tcpClientSocketList列表中將斷開(kāi)連接的TcpClientSocket對(duì)象刪除的功能。其具體代碼如下:void
45、 Server:slotDisconnected(int descriptor) for(int i=0;isocketDescriptor()=descriptor) tcpClientSocketList.removeAt(i); return; return;第51頁(yè),共80頁(yè)。“實(shí)例”TCP服務(wù)器端編程(6)在頭文件“tcpserver.h”中添加如下內(nèi)容:#include server.hprivate:int port; Server *server;public slots: void slotCreateServer(); void updateServer(QString,i
46、nt);第52頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(7)在源文件“tcpserver.cpp”中,在構(gòu)造函數(shù)中添加如下代碼:port=8010;PortLineEdit-setText(QString:number(port);connect(CreateBtn,SIGNAL(clicked(),this,SLOT(slotCreateServer();其中,槽函數(shù)slotCreateServer()用于創(chuàng)建一個(gè)TCP服務(wù)器,具體內(nèi)容如下:void TcpServer:slotCreateServer() server = new Server(this,port);/創(chuàng)建一個(gè)Server
47、對(duì)象 connect(server,SIGNAL(updateServer(QString,int),this, SLOT(updateServer(QString,int);/(a) CreateBtn-setEnabled(false);槽函數(shù)updateServer()用于更新服務(wù)器上的信息顯示,具體內(nèi)容如下:void TcpServer:updateServer(QString msg,int length) ContentListWidget-addItem(msg.left(length);第53頁(yè),共80頁(yè)?!皩?shí)例”TCP服務(wù)器端編程(8)此時(shí),工程中添加了很多文件,工程文件中的
48、內(nèi)容已經(jīng)被改變,需要重新在工程文件“TcpS”中添加:QT += network此時(shí),運(yùn)行服務(wù)器端工程“TcpS”編譯通過(guò)。單擊“創(chuàng)建聊天室”按鈕,便開(kāi)通了一個(gè)TCP聊天室的服務(wù)器,如圖10.12所示。第54頁(yè),共80頁(yè)。04“實(shí)例”TCP客戶端編程第55頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程【例】(難度中等)(CH1005)TCP客戶端編程。建立工程“TcpC”,文件代碼如下。 (1)在頭文件“tcpclient.h”中,TcpClient類繼承自QDialog類,聲明了需要的各種控件,其具體代碼如下:#include #include #include #include #include
49、#include class TcpClient : public QDialog Q_OBJECTpublic: TcpClient(QWidget *parent = 0,Qt:WindowFlags f=0); TcpClient();private: QListWidget *contentListWidget; QLineEdit *sendLineEdit; QPushButton *sendBtn; QLabel *userNameLabel; QLineEdit *userNameLineEdit; QLabel *serverIPLabel; QLineEdit *serve
50、rIPLineEdit; QLabel *portLabel; QLineEdit *portLineEdit; QPushButton *enterBtn; QGridLayout *mainLayout;第56頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程(2)源文件“tcpclient.cpp”的具體代碼如下:#include tcpclient.hTcpClient:TcpClient(QWidget *parent,Qt:WindowFlags f) : QDialog(parent,f) setWindowTitle(tr(TCP Client); contentListWidget =
51、new QListWidget; sendLineEdit = new QLineEdit; sendBtn = new QPushButton(tr(發(fā)送); userNameLabel = new QLabel(tr(用戶名:); userNameLineEdit = new QLineEdit; serverIPLabel = new QLabel(tr(服務(wù)器地址:); serverIPLineEdit = new QLineEdit; portLabel = new QLabel(tr(端口:); portLineEdit = new QLineEdit; enterBtn= new
52、 QPushButton(tr(進(jìn)入聊天室); mainLayout = new QGridLayout(this); mainLayout-addWidget(contentListWidget,0,0,1,2); mainLayout-addWidget(sendLineEdit,1,0); mainLayout-addWidget(sendBtn,1,1); mainLayout-addWidget(userNameLabel,2,0); mainLayout-addWidget(userNameLineEdit,2,1); mainLayout-addWidget(serverIPLa
53、bel,3,0); mainLayout-addWidget(serverIPLineEdit,3,1); mainLayout-addWidget(portLabel,4,0); mainLayout-addWidget(portLineEdit,4,1); mainLayout-addWidget(enterBtn,5,0,1,2);第57頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程(3)客戶端界面如圖10.13所示。第58頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程以上完成了客戶端界面的設(shè)計(jì),下面將完成客戶端的真正聊天功能。(1)在客戶端工程文件“TcpC”中添加如下語(yǔ)句:QT += network
54、(2)在頭文件“tcpclient.h”中添加如下代碼:#include #include private:bool status; int port; QHostAddress *serverIP; QString userName; QTcpSocket *tcpSocket;public slots: void slotEnter(); void slotConnected(); void slotDisconnected(); void dataReceived(); void slotSend();第59頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程(3)在源文件“tcpclient.cpp
55、”中添加頭文件:#include #include 在其構(gòu)造函數(shù)中添加如下代碼:status = false; port = 8010; portLineEdit-setText(QString:number(port); serverIP =new QHostAddress(); connect(enterBtn,SIGNAL(clicked(),this,SLOT(slotEnter(); connect(sendBtn,SIGNAL(clicked(),this,SLOT(slotSend(); sendBtn-setEnabled(false);在以上代碼中,槽函數(shù)slotEnter(
56、)實(shí)現(xiàn)了進(jìn)入和離開(kāi)聊天室的功能。具體代碼。第60頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程其中,(a) if(!status):status表示當(dāng)前的狀態(tài),true表示已經(jīng)進(jìn)入聊天室,false表示已經(jīng)離開(kāi)聊天室。這里根據(jù)status的狀態(tài)決定是執(zhí)行“進(jìn)入”還是“離開(kāi)”的操作。(b) if(!serverIP-setAddress(ip):用來(lái)判斷給定的IP地址能否被正確解析。(c) tcpSocket-connectToHost(*serverIP,port):與TCP服務(wù)器端連接,連接成功后發(fā)出connected()信號(hào)。(d) QString msg=userName+tr(:Leave C
57、hat Room):構(gòu)造一條離開(kāi)聊天室的消息。(e) if(length=tcpSocket-write(msg.toLatin1(),msg.length()!=msg.length():通知服務(wù)器端以上構(gòu)造的消息。(f) tcpSocket-disconnectFromHost():與服務(wù)器斷開(kāi)連接,斷開(kāi)連接后發(fā)出disconnected()信號(hào)。第61頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程在源文件“tcpclient.cpp”中,槽函數(shù)slotConnected()為connected()信號(hào)的響應(yīng)槽,當(dāng)與服務(wù)器連接成功后,客戶端構(gòu)造一條進(jìn)入聊天室的消息,并通知服務(wù)器。其具體代碼如下:v
58、oid TcpClient:slotConnected() sendBtn-setEnabled(true); enterBtn-setText(tr(離開(kāi)); int length=0; QString msg=userName+tr(:Enter Chat Room); if(length=tcpSocket-write(msg.toLatin1(),msg.length()!=msg.length() return; 第62頁(yè),共80頁(yè)?!皩?shí)例”TCP客戶端編程在源文件“tcpclient.cpp”中,槽函數(shù)slotSend()的具體代碼如下:void TcpClient:slotSen
59、d() if(sendLineEdit-text()=) return; QString msg=userName+:+sendLineEdit-text(); tcpSocket-write(msg.toLatin1(),msg.length(); sendLineEdit-clear();在源文件“tcpclient.cpp”中,槽函數(shù)slotDisconnected()的具體內(nèi)容如下:void TcpClient:slotDisconnected() sendBtn-setEnabled(false); enterBtn-setText(tr(進(jìn)入聊天室);第63頁(yè),共80頁(yè)?!皩?shí)例”T
60、CP客戶端編程當(dāng)有數(shù)據(jù)到來(lái)時(shí),觸發(fā)源文件“tcpclient.cpp”的dataReceived()函數(shù),從套接字中將有效數(shù)據(jù)取出并顯示,其代碼如下:void TcpClient:dataReceived() while(tcpSocket-bytesAvailable()0) QByteArray datagram; datagram.resize(tcpSocket-bytesAvailable(); tcpSocket-read(datagram.data(),datagram.size(); QString msg=datagram.data(); contentListWidget-
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 吉林藝術(shù)學(xué)院《外國(guó)文學(xué)》2021-2022學(xué)年第一學(xué)期期末試卷
- 文言主觀簡(jiǎn)答試題專訓(xùn)(二)-2025新高考語(yǔ)文一輪復(fù)習(xí)
- 吉林藝術(shù)學(xué)院《概念設(shè)計(jì)》2021-2022學(xué)年第一學(xué)期期末試卷
- 手工品訂單承攬協(xié)議書(shū)范文范本
- 2024年大學(xué)生接活互助協(xié)議書(shū)模板
- 吉林師范大學(xué)《習(xí)近平總書(shū)記關(guān)于教育的重要論述研究》2021-2022學(xué)年第一學(xué)期期末試卷
- 2024年處理廢石協(xié)議書(shū)模板
- 農(nóng)村地基自建房轉(zhuǎn)讓協(xié)議書(shū)范文
- 畜牧業(yè)對(duì)氣候變化的影響分析報(bào)告
- 企業(yè)衛(wèi)生安全檢查管理制度
- 上海市浦東新區(qū)2023-2024學(xué)年六年級(jí)上學(xué)期期中考試英語(yǔ)試題
- 責(zé)任保險(xiǎn)行業(yè)研究報(bào)告
- (高清版)JGT 225-2020 預(yù)應(yīng)力混凝土用金屬波紋管
- 化學(xué)實(shí)驗(yàn)室安全考試試題-及答案
- 2022年初中一年級(jí)生物上冊(cè)期中試卷及答案
- 四大名著稱四大小說(shuō)三國(guó)演義西游記水滸傳紅樓夢(mèng)中國(guó)古典章回小說(shuō)PPT資料課件
- 一般跨越架搭設(shè)施工方案
- 《羊道春牧場(chǎng)》讀后感作文5篇
- 上消化道大出血的護(hù)理PPT課件
- RPG游戲概要設(shè)計(jì)文檔
- 鐵塔安裝施工方案(完整版)
評(píng)論
0/150
提交評(píng)論