軟件設(shè)計TCPIP網(wǎng)絡(luò)通信程序設(shè)計實驗報告.docx
南京郵電大學(xué)通信與信息工程學(xué)院課程設(shè)計報告201 /201 學(xué)年 第二學(xué)期課程設(shè)計 實驗報告模 塊 名 稱 TCP/IP網(wǎng)絡(luò)通信程序設(shè)計專 業(yè) 學(xué) 生 班 級 學(xué) 生 學(xué) 號 學(xué) 生 姓 名 指 導(dǎo) 教 師 QT5.6環(huán)境下的源代碼目 錄題目1獲取計算機的名稱和IP地址11、設(shè)計內(nèi)容12、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖13、關(guān)鍵實現(xiàn)代碼及注解24、程序運行測試與結(jié)果45、程序設(shè)計中遇到的問題及改進思路4題目2基本C/S模式的通信實驗51、設(shè)計內(nèi)容52、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖53、關(guān)鍵實現(xiàn)代碼及注解84、程序運行測試與結(jié)果215、程序設(shè)計中遇到的問題及改進思路23題目3簡單的瀏覽器的實現(xiàn)241、設(shè)計內(nèi)容242、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖243、關(guān)鍵實現(xiàn)代碼及注解254、程序運行測試與結(jié)果265、程序設(shè)計中遇到的問題及改進思路28題目4利用smtp協(xié)議發(fā)送郵件291、設(shè)計內(nèi)容292、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖293、關(guān)鍵實現(xiàn)代碼及注解304、程序運行測試與結(jié)果375、程序設(shè)計中遇到的問題及改進思路38課程設(shè)計小節(jié)39附錄4039題目1獲取計算機的名稱和IP地址1、設(shè)計內(nèi)容獲取計算機的名稱和IP地址實驗 編寫程序?qū)崿F(xiàn)下述功能:獲取計算機的名稱和IP地址2、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖 Qt Creator是一個用于Qt開發(fā)的輕量級跨平臺集成開發(fā)環(huán)境。Qt Creator可帶來兩大關(guān)鍵益處:提供首個專為支持跨平臺開發(fā)而設(shè)計的集成開發(fā)環(huán)境 (IDE),并確保首次接觸Qt框架的開發(fā)人員能迅速上手和操作。即使不開發(fā)Qt應(yīng)用程序,Qt Creator也是一個簡單易用且功能強大的IDE。Qt數(shù)據(jù)庫中提供QtNetwork Module中的QHostInfo、QHostAddress、QNetworkInterface和QNetAddressEntry等類來查詢網(wǎng)絡(luò)參數(shù)。QNetworkInterface類提供了程序所運行的主機IP地址和網(wǎng)絡(luò)接口信息的列表,在一個網(wǎng)絡(luò)接口信息中,包含一個或多個IP地址,每一個IP地址又包含和它相關(guān)的子網(wǎng)掩碼和廣播地址。它們?nèi)邉e封裝在一個對象中QNetworkAddressEntry,網(wǎng)絡(luò)接口信息也包含了硬件地址信息。1完成界面getHostInformation()函數(shù)獲得主機信息slotDetail()函數(shù)網(wǎng)絡(luò)接口信息運行出結(jié)果3、關(guān)鍵實現(xiàn)代碼及注解1. 在NetworkInformation.pro文件中,添加QT += network2. 在頭文件networkinformation.h中添加如下代碼:#include #include public:void getHostInformation();public slots:void slotDetail();對QHostInfo、QNetworkInterface進行聲明,添加槽函數(shù)。3. 在源文件networkinformation.cpp中添加代碼。其中在構(gòu)造函數(shù)的最后添加:getHostInformation(); /用于獲得主機信息connect(detailBtn,SIGNAL(clicked(),this,SLOT(slotDetail();4. getHostInformation()函數(shù)用于獲得主機信息。具體實現(xiàn)代碼如下:void NetworkInformation:getHostInformation() QString localHostName = QHostInfo:localHostName();/獲得本機主機名 LineEditLocalHostName-setText(localHostName); QHostInfo hostInfo = QHostInfo:fromName(localHostName);/根據(jù)主機名獲得相關(guān)主機信息,包括IP地址等。QHostInfo:fromName()函數(shù)通過主機名查找IP地址信息。 QList listAddress = hostInfo.addresses();/獲得主機的IP地址列表 if(!listAddress.isEmpty()/獲得的主機IP地址列表可能為空。在不為空的情況下使用第一個IP地址。 LineEditAddress-setText(listAddress.first().toString(); 注釋見上。25. slotDetail()函數(shù)獲得與網(wǎng)絡(luò)接口相關(guān)的信息,具體實現(xiàn)代碼如下:void NetworkInformation:slotDetail()/獲得與網(wǎng)絡(luò)接口相關(guān)的信息 QString detail=; QList list=QNetworkInterface:allInterfaces();/QNetworkInterface類提供了一個主機IP地址和網(wǎng)絡(luò)接口的列表 for(int i=0;ilist.count();i+) QNetworkInterface interface=list.at(i); detail=detail+u8設(shè)備:+interface.name()+n;/獲得網(wǎng)絡(luò)接口的名稱 detail=detail+u8硬件地址:+interface.hardwareAddress()+n;/獲得網(wǎng)絡(luò)接口的硬件地址 QList entryList=interface.addressEntries(); /每個網(wǎng)絡(luò)接口包括0個或多個IP地址,每個IP地址有選擇性地與一個子網(wǎng)掩碼和(或)一個廣播地址相關(guān)聯(lián) /QNetworkAddressEntry類存儲了被網(wǎng)絡(luò)接口支持的一個IP地址,同時還包括與之相關(guān)的子網(wǎng)掩碼和廣播地址 for(int j=0;jentryList.count();j+) QNetworkAddressEntry entry=entryList.at(j); detail=detail+t+u8IP 地址:+entry.ip().toString()+n; detail=detail+t+u8子網(wǎng)掩碼:+mask().toString()+n; detail=detail+t+u8廣播地址:+entry.broadcast().toString()+n; QMessageBox:information(this,tr(Detail),detail);4、程序運行測試與結(jié)果 圖1-1 獲取本機網(wǎng)絡(luò)信息 圖1-2 獲取本機詳細(xì)網(wǎng)絡(luò)信息5、程序設(shè)計中遇到的問題及改進思路1. “詳細(xì)”這個按鈕單擊時,沒有明顯的痕跡,故后期添加了一些特效。將PushButton的屬性checkable設(shè)置為真,則運行時鼠標(biāo)單擊一下,按鈕的顏色會變淡,再單擊一下又會變亮,它是以顏色的的深淺來提醒它的toggle的。菜單欄中的一個選項,一般是用trigger來發(fā)射信號。2報錯出現(xiàn)“cannot find file main.pro”,原因是QT所使用的工程,目錄樹中出現(xiàn)漢字,空格等。題目2基本C/S模式的通信實驗1、設(shè)計內(nèi)容基本C/S模式的通信實驗編寫程序?qū)崿F(xiàn)一個基于UDP 模式的通信程序和一個基于TCP 模式的通信程序?;疽螅耗茌斎胗嬎銠C的IP地址和端口號,能輸入、發(fā)送文本信息和顯示接受的文本信息。2、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖一、基于UDP模式在UDP方式下,它是一個不可靠的,面向數(shù)據(jù)報的無連接協(xié)議??蛻舳瞬⒉慌c服務(wù)器建立連接,它只負(fù)責(zé)調(diào)用發(fā)送函數(shù)向服務(wù)器發(fā)出數(shù)據(jù)報。同樣,服務(wù)器也不從客戶端接收連接,只負(fù)責(zé)調(diào)用接收函數(shù),等待來自某客戶端的數(shù)據(jù)到達。Qt中通過QupSocket類實現(xiàn)UDP協(xié)議的編程。Socket簡單地說,就是一個IP 地址加一個port端口。因為要傳輸數(shù)據(jù),就要知道往哪個機子上傳送,而IP 地址確定了一臺主機,但是這臺機子上可能運行著各種各樣的網(wǎng)絡(luò)程序,這時就要使用一個端口來指定UDP 程序。所以說,Socket 指明了數(shù)據(jù)報傳輸?shù)穆窂?。編寫兩個程序,一個用來發(fā)送數(shù)據(jù)報,叫做客戶端;另一個用來接收數(shù)據(jù)報,叫做服務(wù)器端,均應(yīng)用UDP 協(xié)議。這樣也就構(gòu)成了所謂的C/S(客戶端/服務(wù)器)編程模型。首先做服務(wù)器端。先在頭文件udpclient.h中聲明需要的各種控件,完成對應(yīng)源代碼,從而先形成一個服務(wù)器的界面。然后在頭文件udpclient.h中添加需要的槽函數(shù),在源文件udpserver.cpp中添加聲明,設(shè)置好端口參數(shù)(本程序設(shè)置為5555)并且創(chuàng)建QUdpSocket,使程序能夠定向發(fā)送廣播地址。接下來做客戶端。同樣先在頭文件udpclient.h中聲明需要的各種控件,完成對應(yīng)源代碼,從而形成一個客戶端的界面。然后在構(gòu)造函數(shù)中設(shè)置相對應(yīng)的端口號參數(shù)(5555),定義CloseBtnClicked()和dataReceived()函數(shù),最后實現(xiàn)客戶端的功能。圖2-1 UDP協(xié)議工作原理圖2-2 UDP客戶端與服務(wù)器之間的交互方式二、基于TCP模式1.圖2-3 TCP協(xié)議工作原理2. 圖2-4 TCP客戶端與服務(wù)器間的交互時序3.圖2-5 TCP文件傳輸結(jié)構(gòu)3、關(guān)鍵實現(xiàn)代碼及注解一、基于UDP模式服務(wù)器端:1.在UdpServer.pro中添加:QT += network2.在頭文件udpserver.h中添加需要的槽函數(shù):#include /Line11.12聲明,為了在Line21-32添加槽函數(shù)#include public slots: void StartBtnClicked(); void timeout();private: QLabel *TimerLabel; QLineEdit *TextLineEdit; QPushButton *StartBtn; QVBoxLayout *mainLayout; int port; bool isStarted; QUdpSocket *udpSocket;QTimer *timer;3.在udpserver.cpp的槽函數(shù)中添加如下代碼:connect(StartBtn,SIGNAL(clicked(),this,SLOT(StartBtnClicked(); port =6665;/設(shè)置UDP的端口號參數(shù),服務(wù)器定時向此端口發(fā)送廣播消息 isStarted=false; udpSocket = new QUdpSocket(this); timer = new QTimer(this);/創(chuàng)建一個QUdpSocket connect(timer,SIGNAL(timeout(),this,SLOT(timeout();/定時發(fā)送廣播信息4. StartBtnClicked()函數(shù)的具體代碼:void UdpServer:StartBtnClicked()/“開始”按鈕函數(shù)的設(shè)定 if(!isStarted) StartBtn-setText(u8停止); timer-start(1000); isStarted =true; else StartBtn-setText(u8開始); isStarted = false; timer-stop(); 5.timeout()函數(shù)完成了向端口發(fā)送廣播消息的功能:void UdpServer:timeout()/完成向端口發(fā)送廣播信息的功能 QString msg = TextLineEdit-text(); int length=0; if(msg=) return; if(length=udpSocket-writeDatagram(msg.toLatin1(),msg.length(),QHostAddress:Broadcast,port)!=msg.length() return; /QHostAddress:Broadcast指定向廣播地址發(fā)送客戶端:1.在UdpClient.pro中加入代碼:QT += network2.在udpclient.cpp的構(gòu)造函數(shù)中添加代碼:connect(CloseBtn,SIGNAL(clicked(),this,SLOT(CloseBtnClicked(); port =6665;/設(shè)置UDP的端口號參數(shù),指定在此端口上監(jiān)聽數(shù)據(jù) udpSocket = new QUdpSocket(this);/創(chuàng)建一個QUdpSocket connect(udpSocket,SIGNAL(readyRead(),this,SLOT(dataReceived(); /連接QIODevice的readyRead()信號。QUdpSocket也是一個I/O設(shè)備,從QIODevice繼承而來,當(dāng)有數(shù)據(jù)到達I/O設(shè)備時,發(fā)出readyRead()信號 bool result=udpSocket-bind(port);/綁定到指定端口上 if(!result) QMessageBox:information(this,tr(error),tr(udp socket create error!); return;3.定義CloseBtnClicked()函數(shù):void UdpClient:CloseBtnClicked() close();4.定義dataReceived()函數(shù):void UdpClient:dataReceived()/響應(yīng)QUdpSocket的readyRead()信號,一旦UdpSocket對象中有數(shù)據(jù)可讀時,即通過readyDatagram()方法將數(shù)據(jù)讀出并顯示 while(udpSocket-hasPendingDatagrams()/判斷UdpSocket中是否有數(shù)據(jù)報可讀,hasPendingDatagrams()方法在至少有一個數(shù)據(jù)報可讀時返回true,否則返回false QByteArray datagram;/Line47-50實現(xiàn)了讀取第一個數(shù)據(jù)報,pendingDatagramSize()可以獲得第一個數(shù)據(jù)報長度 datagram.resize(udpSocket-pendingDatagramSize(); udpSocket-readDatagram(datagram.data(),datagram.size(); QString msg=datagram.data(); ReceiveTextEdit-insertPlainText(msg);/顯示數(shù)據(jù)內(nèi)容 二、基于TCP模式服務(wù)器端:1.頭文件“tcpserver.h”中聲明了需要的各種控件,TcpServer繼承自Qdialog,實現(xiàn)了服務(wù)器端的對話框顯示與控制。具體代碼如下2:#include #include #include #include #include #include #include server.hclass TcpServer : public QDialog Q_OBJECTpublic: TcpServer(QWidget *parent = 0,Qt:WindowFlags f=0); TcpServer();private: QListWidget *ContentListWidget; QLabel *PortLabel; QLineEdit *PortLineEdit; QPushButton *CreateBtn; QGridLayout *mainLayout; int port; Server *server;2.在源文件“tcpserver.cpp”中,TcpServer類的構(gòu)造函數(shù)主要實現(xiàn)窗體各控件的創(chuàng)建、布局等,其具體代碼如下:#include tcpserver.hTcpServer:TcpServer(QWidget *parent,Qt:WindowFlags f) : QDialog(parent,f) setWindowTitle(tr(TCP Server); ContentListWidget = new QListWidget; PortLabel = new QLabel(u8端口:); PortLineEdit = new QLineEdit; CreateBtn = new QPushButton(u8創(chuàng)建聊天室); mainLayout = new QGridLayout(this); mainLayout-addWidget(ContentListWidget,0,0,1,2); mainLayout-addWidget(PortLabel,1,0); mainLayout-addWidget(PortLineEdit,1,1); mainLayout-addWidget(CreateBtn,2,0,1,2); port=5555; PortLineEdit-setText(QString:number(port); connect(CreateBtn,SIGNAL(clicked(),this,SLOT(slotCreateServer();3. 在工程“TcpServer.pro”中添加如下語句:QT += network4. 在工程“TcpServer.pro”中添加C+類文件“tcpclientsocket.h”及“tcpclientsocket.cpp”,TcpClientSocket繼承自QTcpSocket,創(chuàng)建一個TCP套接字,以便在服務(wù)器端實現(xiàn)與客戶端程序的通信。在源文件“tcpclientsocket.cpp”中,構(gòu)造函數(shù)(TcpClientSocket)的內(nèi)容如下(它指定了信號與槽的連接關(guān)系):#include tcpclientsocket.hTcpClientSocket:TcpClientSocket(QObject *parent)/指定了信號與槽的連接關(guān)系 connect(this,SIGNAL(readyRead(),this,SLOT(dataReceived(); connect(this,SIGNAL(disconnected(),this,SLOT(slotDisconnected();/disconnected()信號在斷開連接時發(fā)出5. 在源文件“tcpclientsocket.cpp”中,dataReceived()函數(shù)的具體代碼如下:void TcpClientSocket:dataReceived()/有數(shù)據(jù)到來時,觸發(fā)dataReceived()函數(shù),從套接字中將有效數(shù)據(jù)取出,然后發(fā)出updateClients()信號。 while(bytesAvailable()0) int length = bytesAvailable(); char buf1024; read(buf,length); QString msg=buf; emit updateClients(msg,length);/updateClients()信號是通知服務(wù)器向聊天室內(nèi)的所有成員廣播信息 6.在工程“TcpServer.pro”中添加C+類文件“server.h”及“server.cpp”,Server繼承自QTcpServer,實現(xiàn)一個TCP協(xié)議的服務(wù)器。利用QTcpServer,開發(fā)著可以監(jiān)聽到指定端口的TCP連接。其具體代碼如下:#include #include #include tcpclientsocket.h/包含TCP套接字class Server : public QTcpServer Q_OBJECT /添加宏(Q_OBJECT)是為了實現(xiàn)信號與槽的通信public: Server(QObject *parent=0,int port=0); QList tcpClientSocketList;/用來保存與每一個客戶端連接的TcpClientSocketsignals: void updateServer(QString,int);public slots: void updateClients(QString,int); void slotDisconnected(int);protected: void incomingConnection(int socketDescriptor);7.在源文件“server.cpp”中,構(gòu)造函數(shù)(Server)的具體內(nèi)容如下:#include server.hServer:Server(QObject *parent,int port) :QTcpServer(parent) listen(QHostAddress:Any,port);/在指定的端口對任意地址進行監(jiān)聽8. 在源文件“server.cpp”中,當(dāng)出現(xiàn)一個新的連接時,QTcpServer會立即觸發(fā)incomingConnection()函數(shù),參數(shù)socketDescriptor指定了連接的Socket描述符,其具體代碼如下:void Server:incomingConnection(int socketDescriptor)/出現(xiàn)一個新的連接時,QTcpServer觸發(fā)incomingConnection()函數(shù) TcpClientSocket *tcpClientSocket=new TcpClientSocket(this);/創(chuàng)建一個新的TcpClientSocket與客戶端通信 connect(tcpClientSocket,SIGNAL(updateClients(QString,int),this,SLOT(updateClients(QString,int);/連接TcpClientSocket的updateClients信號 connect(tcpClientSocket,SIGNAL(disconnected(int),this,SLOT(slotDisconnected(int);/連接TcpClientSocket的disconnected信號 tcpClientSocket-setSocketDescriptor(socketDescriptor);/將新創(chuàng)建的TcpClientSocket的套接字描述符指定為參數(shù)socketDescriptor tcpClientSocketList.append(tcpClientSocket);/將tcpClientSocketList加入客戶端套接字列表以便管理9. 在源文件“server.cpp”中,updateClients()函數(shù)將任意客戶端發(fā)來的信息進行廣播,保證聊天室的所有客戶均能看到其他人的發(fā)言。其具體代碼如下:void Server:updateClients(QString msg,int length)/將任意客戶端發(fā)來的信息進行廣播,保證聊天室的所有客戶均能看到其他人的發(fā)言 emit updateServer(msg,length); for(int i=0;iwrite(msg.toLatin1(),length)!=length) continue; 10. 在源文件“tcpserver.cpp”中,槽函數(shù)slotCreateServer()用于創(chuàng)建一個TCP服務(wù)器,具體內(nèi)容如下:void TcpServer:slotCreateServer()/創(chuàng)建一個TCP服務(wù)器 server = new Server(this,port);/創(chuàng)建一個Server對象 connect(server,SIGNAL(updateServer(QString,int),this,SLOT(updateServer(QString,int);/將Server對象的updateServer()信號與相應(yīng)的槽函數(shù)進行連接 CreateBtn-setEnabled(false);客戶端:1.源文件“tcpclient.cpp”的具體代碼如下:#include tcpclient.h#include #include TcpClient:TcpClient(QWidget *parent,Qt:WindowFlags f) : QDialog(parent,f) setWindowTitle(tr(TCP Client); contentListWidget = new QListWidget; sendLineEdit = new QLineEdit; sendBtn = new QPushButton(u8發(fā)送); userNameLabel = new QLabel(u8用戶名:); userNameLineEdit = new QLineEdit; serverIPLabel = new QLabel(u8服務(wù)器地址:); serverIPLineEdit = new QLineEdit; portLabel = new QLabel(u8端口:); portLineEdit = new QLineEdit; enterBtn= new QPushButton(u8進入聊天室); 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(serverIPLabel,3,0); mainLayout-addWidget(serverIPLineEdit,3,1); mainLayout-addWidget(portLabel,4,0); mainLayout-addWidget(portLineEdit,4,1); mainLayout-addWidget(enterBtn,5,0,1,2);2.在客戶端工程文件“TcpClient.pro”中添加如下語句:QT += network3.在源文件“tcpclient.cpp”的構(gòu)造函數(shù)中添加如下代碼:status = false; port = 5555; /隨意設(shè)置端口號 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()實現(xiàn)了進入和離開聊天室的功能。具體代碼如下:void TcpClient:slotEnter()/實現(xiàn)了進入和離開聊天室的功能 if(!status) QString ip = serverIPLineEdit-text(); if(!serverIP-setAddress(ip) QMessageBox:information(this,tr(error),tr(server ip address error!); return; if(userNameLineEdit-text()=) QMessageBox:information(this,tr(error),tr(User name error!); return; userName=userNameLineEdit-text(); tcpSocket = new QTcpSocket(this); connect(tcpSocket,SIGNAL(connected(),this,SLOT(slotConnected(); connect(tcpSocket,SIGNAL(disconnected(),this,SLOT(slotDisconnected(); connect(tcpSocket,SIGNAL(readyRead(),this,SLOT(dataReceived(); tcpSocket-connectToHost(*serverIP,port); status=true; else int length=0; QString msg=userName+tr(:Leave Chat Room); if(length=tcpSocket-write(msg.toLatin1(),msg.length()!=msg. length() return; tcpSocket-disconnectFromHost(); status=false; 4. 槽函數(shù)slotConnected():void TcpClient:slotConnected()/槽函數(shù)slotConnected()為connected()信號的響應(yīng)槽,當(dāng)與服務(wù)器連接成功后,客戶端構(gòu)造一條進入聊天室的消息,并通知服務(wù)器 sendBtn-setEnabled(true); enterBtn-setText(u8離開); int length=0; QString msg=userName+tr(:Enter Chat Room); if(length=tcpSocket-write(msg.toLatin1(),msg.length()!=msg.length() return; 5.源文件“tcpclient.cpp”中的dataReceived()函數(shù):void TcpClient:dataReceived()/有數(shù)據(jù)到來時,觸發(fā)此函數(shù),從套接字中將有效數(shù)據(jù)取出并顯示 while(tcpSocket-bytesAvailable()0) QByteArray datagram; datagram.resize(tcpSocket-bytesAvailable(); tcpSocket-read(datagram.data(),datagram.size(); QString msg=datagram.data(); contentListWidget-addItem(msg.left(datagram.size(); 4、程序運行測試與結(jié)果一、基于UDP模式圖2-6 服務(wù)器端窗口圖2-7 客戶端窗口說明:打開服務(wù)器端口,輸入字符(最好是英文字符),同時打開客戶端。在服務(wù)器端點擊“開始”按鈕,便以時鐘間隔向客戶端發(fā)送輸入的字符,同時顯示在客戶端窗口上,直到點擊“停止”按鈕,才終止發(fā)送。二、基于TCP模式圖2-8服務(wù)器端窗口圖2-9 客戶端窗口說明: 操作方式類似于UDP。點擊發(fā)送即可進行客戶端和服務(wù)器之間的對話。5、程序設(shè)計中遇到的問題及改進思路1. 出現(xiàn)field m_createDate has incomplete type錯誤。由于只在頭文件中加了class聲明,如class QDateTime,在cpp文件中也使用#include 將該類引入,但由于使用QDateTime m_createDate;方式為創(chuàng)建了QDateTime對象,但由于只是對QDateTime類進行了聲明而隱藏了類的實現(xiàn),此時編譯時不知道QDateTime的完成實現(xiàn)所以無法創(chuàng)建QDateTime對象。解決方法是在頭文件中使用#include 方式替換class QDateTime。2出現(xiàn)“QApplication: No such file or directory”報錯。則檢查工程文件中*.pro中是否有“QT += widgets”,若沒有,則需要在工程文件*.pro下增加一條:“QT += widgets”,則問題就可以解決了。3出現(xiàn)“error: tr was not declared in this scope”,tr這個函數(shù)是QObject對象中的靜態(tài)成員函數(shù),因此使用的時候,如果不是用類來寫的話,就會報這個錯誤,只需要在tr函數(shù)前加上“QObject:”,如:“QObject:tr(a button)”這樣既可。題目3簡單的瀏覽器的實現(xiàn)1、設(shè)計內(nèi)容簡單的瀏覽器的實現(xiàn):設(shè)計一個簡單的瀏覽器。基本要求:在菜單項或工具條實現(xiàn)打開一個新的網(wǎng)頁指定的功能。提高要求:在菜單項或工具條實現(xiàn)下述功能之一:清除自動密碼歷史記錄。瀏覽器地址欄歷史地址的清除。清空臨時目錄。2、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖Qt5開始,應(yīng)用層的編程使用QNetworkRequest、QNetworkReply和QNetworkAccessManager這幾個高層次的類。其中,網(wǎng)絡(luò)請求由QnetworkRequest類來表示,作為與請求有關(guān)的信息的統(tǒng)一容器,在創(chuàng)建請求對象時指定的URL決定了請求使用的協(xié)議,目前支持HTTP、FTP和本地文件URLs的上傳和下載;QnetworkAccessManager類用于協(xié)調(diào)網(wǎng)絡(luò)操作,每當(dāng)一個請求創(chuàng)建后,該類用來調(diào)度它,并發(fā)射信號來報告進度;而對于網(wǎng)絡(luò)請求的應(yīng)答則使用QnetworkReply類表示,它會在請求被完成調(diào)度時由QnetworkAccessManager創(chuàng)建。新建Qt Gui應(yīng)用,名稱為“myHTTP”,類名為“MainWindow”。完成后進入設(shè)計模式,即打開ui界面設(shè)計,向界面上拖入一個Text Browser窗口,然后在頭文件和源文件中加入相應(yīng)代碼。圖3-1 瀏覽器與服務(wù)器的連接過程圖3-2 ui界面的設(shè)計3、關(guān)鍵實現(xiàn)代碼及注解1.進入“mainwindow.h”文件,首先添加類的前置聲明: class QNetworkReply; /Line5.6為類的前置聲明class QNetworkAccessManager;2.添加一個私有對象定義:QNetworkAccessManager *manager;3.添加一個私有槽的聲明:private slots:void replyFinished(QNetworkReply *);/此私有槽聲明上面的私有對象4.在“mainwindow.cpp”文件中添加頭文件:#include 然后在構(gòu)造函數(shù)中添加如下代碼:manager = new QNetworkAccessManager(this);/首先創(chuàng)建一個QNetworkAccessManager類的實例,用來發(fā)送網(wǎng)絡(luò)請求和接收應(yīng)答 connect(manager,SIGNAL(finished(QNetworkReply*),this,SLOT(replyFinished(QNetworkReply*);/關(guān)聯(lián)管理器的finished()信號和自定義的槽,每當(dāng)網(wǎng)絡(luò)應(yīng)答結(jié)束時都會發(fā)射這個信號manager-get(QNetworkRequest(QUrl(http:/);/使用get()函數(shù)發(fā)送一個網(wǎng)絡(luò)請求,請求使用QNetworkRequest類表示,get()函數(shù)返回一個QNetworkReply類對象5.添加槽的定義:void MainWindow:replyFinished(QNetworkReply *reply) QString all = reply-readAll(); ui-textBrowser-setText(all); reply-deleteLater(); 因為QNetworkReply繼承自QIODevice類,所以可以像操作一般的I/O設(shè)備一樣操作該類。這里使用了readAll()函數(shù)來讀取所有的應(yīng)答數(shù)據(jù)。在完成數(shù)據(jù)的讀取后,需要使用deleteLater()刪除reply對象。4、程序運行測試與結(jié)果 先實現(xiàn)網(wǎng)頁上文字鏈接的顯示。如圖3-3.圖3-3然后查閱網(wǎng)上資料,完成完整的瀏覽器設(shè)計??梢暂斎刖W(wǎng)址瀏覽網(wǎng)頁,可以將網(wǎng)頁添加到收藏夾,可以生成瀏覽歷史記錄。如圖3-4,3-5.圖3-4圖3-55、程序設(shè)計中遇到的問題及改進思路1. 當(dāng)使用tr進行語言國際化時,有可能會出現(xiàn)錯誤:error : tr was not declared in this scope。解決方法:在程序中加入#include,并使用QObject:tr();2. 編譯時遇到“No rule to make target xxx.cpp, needed by debug/xxx.o. Stop.”的問題,出現(xiàn)該問題的原因為,在.pro文件中包含了某.cpp文件和.h文件,但是在項目中可能因為該文件未被使用,在本地直接刪掉了該文件,而.pro文件中還包含了這兩個文件的引用,此時編譯就會出現(xiàn)以上問題。解決辦法是在.pro文件中刪除“xxx.cpp”和“xxx.h”的引用即可。題目4利用smtp協(xié)議發(fā)送郵件1、設(shè)計內(nèi)容利用smtp協(xié)議發(fā)送郵件基本要求:能發(fā)送內(nèi)容為文本信息的郵件。提高要求:能發(fā)送帶有附件信息的郵件。2、設(shè)計分析論述及程序?qū)崿F(xiàn)流程框圖SMTP稱為簡單郵件傳輸協(xié)議(Simple Mail Transfer Protocal),目標(biāo)是向用戶提供高效、可靠的郵件傳輸。它的一個重要特點是它能夠在傳送中接力傳送郵件,即郵件可以通過不同網(wǎng)絡(luò)上的主機接力式傳送。通常它工作在兩種情況下:一是郵件從客戶機傳輸?shù)椒?wù)器;二是從某一個服務(wù)器傳輸?shù)搅硪粋€服務(wù)器。SMTP是一個請求/響應(yīng)協(xié)議,它監(jiān)聽25號端口,用于接收用戶的Mail請求,并與遠端Mail服務(wù)器建立SMTP連接。SMTP通常有兩種工作模式。發(fā)送SMTP和接收SMTP。具體工作方式為:發(fā)送SMTP在接收到用戶的郵件請求后,判斷此郵件是否為本地郵件,若是直接投送到用戶的郵箱,否則向DNS查詢遠端郵件服務(wù)器的MX記錄,并建立與遠端接收SMTP之間的一個雙向傳送通道,此后SMTP命令由發(fā)送SMTP發(fā)出,由接收SMTP接收,而應(yīng)答則反方向傳送。一旦傳送通道建立,SMTP發(fā)送者發(fā)送MAIL命令指明郵件發(fā)送者。如果SMTP接收者可以接收郵件則返回OK應(yīng)答。SMTP發(fā)送者再發(fā)出RCPT命令確認(rèn)郵件是否接收到。如果SMTP接收者接收,則返回OK應(yīng)答;如果不能接收到,則發(fā)出拒絕接收應(yīng)答(但不中止整個郵件操作),雙方將如此反復(fù)多次。當(dāng)接收者收到全部郵件后會接收到特別的序列,入伏哦接收者成功處理了郵件,則返回OK應(yīng)答。SMTP的連接和發(fā)送過程大致如下:(1)建立TCP連接;(2)客戶端發(fā)送HELO命令以標(biāo)識發(fā)件人自己的身份,然后客戶端發(fā)送MAIL命令。服務(wù)器端正希望以O(shè)K作為響應(yīng),表明準(zhǔn)備接收;(3)客戶端發(fā)送RCPT命令,以標(biāo)識該電子郵件的計劃接收人,可以有多個RCPT行。服務(wù)器端則表示是否愿意為收件人接收郵件;(4)協(xié)商結(jié)束,發(fā)送郵件,用命令DATA發(fā)送;(5)以.表示結(jié)束輸入內(nèi)容一起發(fā)送出去;(6)結(jié)束此次發(fā)送,用QUIT命令退出。3、關(guān)鍵實現(xiàn)代碼及注解1.在SMTP.pro文件中加入如下代碼,依次讀取工程目錄中其他文件夾的內(nèi)容:SOURCES += src/emailaddress.cpp src/mimeattachment.cpp src/mimefile.cpp src/mimehtml.cpp src/mimeinlinefile.cpp src/mimemessage.cpp src/mimepart.cpp src/mimetext.cpp src/smtpclient.cpp src/quotedprintable.cpp src/mimemultipart.cpp src/mimecontentformatter.cpp src/main.cpp src/sendemail.cppHEADERS += src/emailaddress.h src/mimeattachment.h src/mim