1 獲取本機網絡與通信
在網絡應用中,經常需要獲得本機的主機名.IP地址和硬件地址等網絡信息.運用QHostInfo,QNetWorkInterface,QNetworkAddressEntry可獲得本機的網絡信息.
- widget.h
1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 #include <QLabel> 6 #include <QPushButton> 7 #include <QLineEdit> 8 #include <QGridLayout> 9 #include <QMessageBox> 10 11 #include <QHostInfo> 12 #include <QNetworkInterface> 13 14 15 namespace Ui { 16 class Widget; 17 } 18 19 class Widget : public QWidget 20 { 21 Q_OBJECT 22 23 public: 24 explicit Widget(QWidget *parent = 0); 25 ~Widget(); 26 27 private: 28 QLabel *hostLabel; 29 QLineEdit *LineEditLocalHostName; 30 QLabel *ipLabel; 31 QLineEdit *LineEditAddress; 32 33 QPushButton *detailBtn; 34 35 QGridLayout *mainLayout; 36 37 private: 38 Ui::Widget *ui; 39 40 public: 41 void getHostInformation(); 42 43 public slots: 44 void slotDetail(); 45 }; 46 47 #endif // WIDGET_H
- widget.cpp
1 #include "widget.h" 2 #include "ui_widget.h" 3 4 Widget::Widget(QWidget *parent) : 5 QWidget(parent), 6 ui(new Ui::Widget) 7 { 8 ui->setupUi(this); 9 hostLabel = new QLabel(tr("主機名: ")); 10 LineEditLocalHostName = new QLineEdit; 11 ipLabel = new QLabel(tr("IP 地址:")); 12 LineEditAddress = new QLineEdit; 13 14 detailBtn = new QPushButton(tr("詳細")); 15 16 mainLayout = new QGridLayout(this); 17 mainLayout->addWidget(hostLabel,0,0); 18 mainLayout->addWidget(LineEditLocalHostName,0,1); 19 mainLayout->addWidget(ipLabel,1,0); 20 mainLayout->addWidget(LineEditAddress,1,1); 21 //第二行第0個,占兩列 22 mainLayout->addWidget(detailBtn,2,0,1,2); 23 24 getHostInformation(); 25 connect(detailBtn,SIGNAL(clicked(bool)),this,SLOT(slotDetail())); 26 } 27 28 Widget::~Widget() 29 { 30 delete ui; 31 } 32 33 void Widget::getHostInformation() 34 { 35 //獲得本機主機名.QHostInfo提供了一系列有關網絡信息的靜態函數, 36 //可以根據主機名獲得分配的IP地址,也可以根據IP地址獲得相應的主機名 37 QString localHostName = QHostInfo::localHostName(); 38 LineEditLocalHostName->setText(localHostName); 39 40 //根據主機名獲得相關主機信息,包括IP地址等. 41 //QHostInfo::fromName()函數通過主機名查找IP地址信息 42 QHostInfo hostInfo = QHostInfo::fromName(localHostName); 43 44 //獲得主機的IP地址列表 45 QList<QHostAddress> listAddress = hostInfo.addresses(); 46 47 //在不為空的情況下,使用第一個IP地址 48 if(!listAddress.isEmpty()) 49 { 50 LineEditAddress->setText(listAddress.first().toString()); 51 } 52 } 53 54 void Widget::slotDetail() 55 { 56 QString detail=""; 57 //QNetworkInterface類提供了一個IP地址和網絡接口的列表 58 QList<QNetworkInterface> list=QNetworkInterface::allInterfaces(); 59 60 for(int i=0;i<list.count();i++) 61 { 62 QNetworkInterface interface=list.at(i); 63 64 //獲得網絡接口的名稱 65 detail=detail+tr("設備: ")+interface.name()+"\n"; 66 //獲得網絡接口的名稱 67 detail=detail+tr("硬件地址:")+interface.hardwareAddress()+"\n"; 68 69 //每個網絡接口包括0個或多個IP地址, 70 //每個IP地址有選擇性地與一個子網掩碼和一個廣播地址相關聯 71 //QNetworkAddressEntry類存儲了被網絡接口支持的一個IP地址, 72 //同時還包括與之相關的子網掩碼和廣播地址 73 QList<QNetworkAddressEntry> entryList=interface.addressEntries(); 74 75 76 for(int j=0;j<entryList.count();j++) 77 { 78 QNetworkAddressEntry entry = entryList.at(j); 79 detail=detail+"\t"+tr("IP地址: ")+entry.ip().toString()+"\n"; 80 detail=detail+"\t"+tr("子網掩碼: ")+entry.netmask().toString()+"\n"; 81 detail=detail+"\t"+tr("廣播地址: ")+entry.broadcast().toString()+"\n"; 82 } 83 QMessageBox::information(this,tr("Detail"),detail); 84 } 85 }
- main.cpp
1 #include "widget.h" 2 #include <QApplication> 3 4 int main(int argc, char *argv[]) 5 { 6 QApplication a(argc, argv); 7 Widget w; 8 w.show(); 9 10 return a.exec(); 11 }
2 基於UDP的網絡廣播程序
2.1 UDP(user data protocol)是一種簡單輕量級,不可靠,面向數據報無連接的傳輸協議,可以用在不是十分重要的場合
2.2 UDP編程模型
在UDP方式下客戶端並不與服務器建立連接,它只負責調用發送函數向服務器法術數據報.類似的服務器不從客戶端接收連接,只負責調用接收函數,等待來自某客戶端的數據到達.Qt中通過QUdpSocket類實現UDP協議的編程.
服務器端:
- udpserver.h
1 #ifndef UDPSERVER_H 2 #define UDPSERVER_H 3 4 #include <QDialog> 5 #include <QLabel> 6 #include <QPushButton> 7 #include <QVBoxLayout> 8 #include <QLineEdit> 9 #include <QUdpSocket> 10 #include <QTimer> 11 12 namespace Ui { 13 class UdpServer; 14 } 15 16 class UdpServer : public QDialog 17 { 18 Q_OBJECT 19 20 public: 21 explicit UdpServer(QWidget *parent = 0,Qt::WindowFlags f=0); 22 ~UdpServer(); 23 24 public slots: 25 void StartBtnClicked(); 26 void timeout(); 27 28 private: 29 int port; 30 bool isStarted; 31 QUdpSocket *udpSocket; 32 QTimer *timer; 33 34 private: 35 QLabel *TimerLabel; 36 QLineEdit *TextLineEdit; 37 QPushButton *StartBtn; 38 QVBoxLayout *mainLayout; 39 40 private: 41 Ui::UdpServer *ui; 42 43 44 }; 45 46 #endif // UDPSERVER_H
- udpserver.cpp
1 #include "udpserver.h" 2 #include "ui_udpserver.h" 3 4 #include <QHostAddress> 5 6 UdpServer::UdpServer(QWidget *parent,Qt::WindowFlags f) : 7 QDialog(parent,f), 8 ui(new Ui::UdpServer) 9 { 10 ui->setupUi(this); 11 12 setWindowTitle(tr("UDP 服務器")); 13 14 TimerLabel = new QLabel(tr("計時器:"),this); 15 TextLineEdit = new QLineEdit(this); 16 StartBtn = new QPushButton(tr("開始"),this); 17 18 //設置垂直布局 19 mainLayout = new QVBoxLayout(this); 20 mainLayout->addWidget(TimerLabel); 21 mainLayout->addWidget(TextLineEdit); 22 mainLayout->addWidget(StartBtn); 23 24 connect(StartBtn,SIGNAL(clicked(bool)),this,SLOT(StartBtnClicked())); 25 26 //設置UDP的端口號參數,服務器定時向此端口發送廣播消息 27 port = 5555; 28 isStarted = false; 29 udpSocket = new QUdpSocket(this); 30 //創建定時器 31 timer = new QTimer(this); 32 //定時發送廣播消息 33 connect(timer,SIGNAL(timeout()),this,SLOT(timeout())); 34 } 35 36 UdpServer::~UdpServer() 37 { 38 delete ui; 39 } 40 41 void UdpServer::StartBtnClicked() 42 { 43 //打開 44 if(!isStarted) 45 { 46 StartBtn->setText(tr("停止")); 47 //每隔1000秒發送一個消息 48 timer->start(1000); 49 isStarted=true; 50 } 51 else 52 { 53 StartBtn->setText(tr("開始")); 54 isStarted = false; 55 timer->stop(); 56 } 57 } 58 59 void UdpServer::timeout() 60 { 61 QString msg = TextLineEdit->text(); 62 int length=0; 63 if(msg=="") 64 { 65 return; 66 } 67 68 //QHostAddress::Broadcast 指定向廣播地址發送 69 if(length=udpSocket->writeDatagram(msg.toLatin1(), 70 msg.length(),QHostAddress::Broadcast,port)!=msg.length()) 71 { 72 return; 73 } 74 }
- udpclient.h
1 #ifndef UDPCLIENT_H 2 #define UDPCLIENT_H 3 4 #include <QDialog> 5 #include <QVBoxLayout> 6 #include <QTextEdit> 7 #include <QPushButton> 8 #include <QUdpSocket> 9 10 namespace Ui { 11 class UdpClient; 12 } 13 14 class UdpClient : public QDialog 15 { 16 Q_OBJECT 17 18 public: 19 explicit UdpClient(QWidget *parent = 0); 20 ~UdpClient(); 21 22 public slots: 23 void CloseBtnClicked(); 24 void dataReceived(); 25 26 private: 27 int port; 28 QUdpSocket *udpSocket; 29 30 private: 31 Ui::UdpClient *ui; 32 QTextEdit *ReceiveTextEdit; 33 QPushButton *closeBtn; 34 QVBoxLayout *mainLayout; 35 }; 36 37 #endif // UDPCLIENT_H
- udpclient.cpp
1 #include "udpclient.h" 2 #include "ui_udpclient.h" 3 #include <QMessageBox> 4 #include <QHostAddress> 5 6 UdpClient::UdpClient(QWidget *parent) : 7 QDialog(parent), 8 ui(new Ui::UdpClient) 9 { 10 ui->setupUi(this); 11 12 setWindowTitle(tr("UDP 客戶端")); 13 14 ReceiveTextEdit = new QTextEdit(this); 15 16 closeBtn = new QPushButton(tr("關閉"),this); 17 18 mainLayout = new QVBoxLayout(this); 19 mainLayout->addWidget(ReceiveTextEdit); 20 mainLayout->addWidget(closeBtn); 21 22 connect(closeBtn,SIGNAL(clicked(bool)),this,SLOT(CloseBtnClicked())); 23 24 //設置UDP的端口號參數,指定在此端口上監聽數據 25 port = 5555; 26 27 //創建一個QUdpSocket 28 udpSocket = new QUdpSocket(this); 29 //連接QIODevice的readyRead()信號 30 //QUdpSocket也是一個I/O設備,從QIODevice繼承而來,當有數據到達I/O設備時,發出readyRead()信號 31 connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived())); 32 33 //綁定到指定的端口上 34 bool result=udpSocket->bind(port); 35 36 if(!result) 37 { 38 QMessageBox::information(this,tr("error"),tr("udp socket create error!")); 39 return; 40 } 41 } 42 43 UdpClient::~UdpClient() 44 { 45 delete ui; 46 } 47 48 void UdpClient::CloseBtnClicked() 49 { 50 close(); 51 } 52 53 void UdpClient::dataReceived() 54 { 55 //判斷UdpSocket中是否有數據報可讀 56 //hasPendingDatagrams()方法在至少有一個數據報可讀時返回true 57 while(udpSocket->hasPendingDatagrams()) 58 { 59 //實現讀取第一個數據報 60 //pendingDataSize()可以獲得第一個數據報的長度 61 QByteArray datagram; 62 datagram.resize(udpSocket->pendingDatagramSize()); 63 udpSocket->readDatagram(datagram.data(),datagram.size()); 64 65 QString msg = datagram.data(); 66 //顯示數據內容 67 ReceiveTextEdit->insertPlainText(msg); 68 } 69 }
3 基於TCP的網絡聊天室程序
TCP協議能為應用程序提供可靠的通信連接,使一台計算機發出的字節流無差錯地送達網絡上的其他計算機.因此,對可靠性要求高的數據通信系統往往使用TCP協議傳輸數據,但在正則收發數據前通信雙方必須首先建立連接.
首先啟動服務器,一段時間后啟動客戶端,它與此服務器經過三次握手后建立連接.此后的一段時間內,客戶端向服務器發送一個請求,服務器處理這個請求,並為客戶端發回一個響應.這個過程一直持續下去,知道客戶端為服務器發一個文件結束符,並關閉客戶端連接,接着服務器也關閉服務器的連接,結束運行或等待一個新的客戶端連接.
Qt中通過QTcpSocket類實現TCP協議的編程.
代碼示例:
服務器端
- tcpserver.h
1 #ifndef TCPSERVER_H 2 #define TCPSERVER_H 3 4 #include <QDialog> 5 #include <QListWidget> 6 #include <QLabel> 7 #include <QLineEdit> 8 #include <QPushButton> 9 #include <QGridLayout> 10 #include "serverh.h" 11 12 namespace Ui { 13 class TcpServer; 14 } 15 16 class TcpServer : public QDialog 17 { 18 Q_OBJECT 19 20 public: 21 explicit TcpServer(QWidget *parent = 0); 22 ~TcpServer(); 23 24 private: 25 Ui::TcpServer *ui; 26 QListWidget *ContentListWidget; 27 QLabel *PortLabe; 28 QLineEdit *PortLineEdit; 29 QPushButton *CreateBtn; 30 QGridLayout *mainLayout; 31 32 private: 33 int port; 34 serverh *server; 35 36 public slots: 37 void slotCreateServer(); 38 void updateServer(QString,int); 39 40 }; 41 42 #endif // TCPSERVER_H
- tcpserver.cpp
1 #include "tcpserver.h" 2 #include "ui_tcpserver.h" 3 4 TcpServer::TcpServer(QWidget *parent) : 5 QDialog(parent), 6 ui(new Ui::TcpServer) 7 { 8 ui->setupUi(this); 9 10 setWindowTitle(tr("TCP Server")); 11 12 ContentListWidget = new QListWidget; 13 14 PortLabe = new QLabel(tr("端口: ")); 15 PortLineEdit = new QLineEdit(); 16 17 CreateBtn = new QPushButton(tr("創建聊天室")); 18 19 mainLayout=new QGridLayout(this); 20 mainLayout->addWidget(ContentListWidget,0,0,1,2); 21 mainLayout->addWidget(PortLabe,1,0); 22 mainLayout->addWidget(PortLineEdit,1,1); 23 mainLayout->addWidget(CreateBtn,2,0,1,2); 24 25 port=8010; 26 PortLineEdit->setText(QString::number(port)); 27 28 connect(CreateBtn,SIGNAL(clicked(bool)),this,SLOT(slotCreateServer())); 29 } 30 31 TcpServer::~TcpServer() 32 { 33 delete ui; 34 } 35 36 void TcpServer::slotCreateServer() 37 { 38 //創建一個serverh對象 39 server = new serverh(this,port); 40 //將serverh對象的updateServer()信號與相應的槽函數進行連接 41 connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int))); 42 43 CreateBtn->setEnabled(false); 44 } 45 46 void TcpServer::updateServer(QString msg , int length) 47 { 48 ContentListWidget->addItem(msg.left(length)); 49 }
- server.h
1 #ifndef SERVERH_H 2 #define SERVERH_H 3 4 #include <QTcpServer> 5 #include <QObject> 6 7 #include "tcpclientsocket.h"//包含TCP的套接字 8 9 class serverh : public QTcpServer 10 { 11 Q_OBJECT 12 public: 13 serverh(QObject *parent=0,int port=0); 14 //用來保存與每一個客戶端連接的TcpClientSocket 15 QList<tcpclientsocket*> tcpClientSocketList; 16 17 signals: 18 void updateServer(QString,int); 19 20 public slots: 21 void updateClients(QString,int); 22 void slotDisconnected(int); 23 24 protected: 25 void incomingConnection(int socketDescriptor); 26 }; 27 28 #endif // SERVERH_H
-
server.cpp
1 #include "serverh.h" 2 3 serverh::serverh(QObject *parent,int port):QTcpServer(parent) 4 { 5 //在指定的端口對任意地址進行監聽 6 //QHostAddress定義了幾種特殊的IP地址 7 //QHostAddress定義了幾種特殊的IP地址,QHostAddress::Null表示一個空的地址 8 //QHostAddress::LocalHost表示IPV4的本機地址127.0.0.1 9 //QHostAddress::LocalHostIPV6表示IPv6的本機地址 10 //QHostAddress::Broadcast表示廣播地址255.255.255.255 11 //QHostAddress::Any表示Ipv4的任意地址0.0.0.0 12 //QHostAddress::AnyIPv6表示IPv6的任意地址 13 listen(QHostAddress::Any,port); 14 } 15 16 //當出現一個新的連接時,QTcpServer觸發incomingConnection()函數,參數 17 //socketDescriptor指定連接的Socket描述符 18 void serverh::incomingConnection(int socketDescriptor) 19 { 20 qDebug() << "receive connect" << endl; 21 //創建一個新的TcpClientSocket客戶端通信 22 tcpclientsocket *tcpClientSocket = new tcpclientsocket(this); 23 //連接TcpClientSocket的updateClients信號 24 connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this, 25 SLOT(updateClients(QString,int))); 26 //連接TcpClientSocket的disconnect信號 27 connect(tcpClientSocket,SIGNAL(disconnected(int)),this, 28 SLOT(slotDisconnected(int))); 29 30 //將tcpClient加入客戶端套接字列表以便管理 31 tcpClientSocket->setSocketDescriptor(socketDescriptor); 32 33 tcpClientSocketList.append(tcpClientSocket); 34 } 35 36 void serverh::updateClients(QString msg, int length) 37 { 38 //發出updateServer信號,來通知服務器對話框更新相應的顯示狀態 39 qDebug() << msg << endl; 40 emit updateServer(msg,length); 41 qDebug() << msg << endl; 42 for(int i=0;i<tcpClientSocketList.count();i++) 43 { 44 QTcpSocket *item = tcpClientSocketList.at(i); 45 if(item->write(msg.toLatin1(),length)!=length) 46 { 47 continue; 48 } 49 } 50 } 51 52 void serverh::slotDisconnected(int descriptor) 53 { 54 for(int i=0;i<tcpClientSocketList.count();i++) 55 { 56 QTcpSocket *item = tcpClientSocketList.at(i); 57 58 if(item->socketDescriptor()==descriptor) 59 { 60 tcpClientSocketList.removeAt(i); 61 return; 62 } 63 } 64 return; 65 }
- tcpclientsocket.h
1 #ifndef TCPCLIENTSOCKET_H 2 #define TCPCLIENTSOCKET_H 3 4 #include <QTcpSocket> 5 #include <QObject> 6 7 class tcpclientsocket : public QTcpSocket 8 { 9 Q_OBJECT //添加宏是為了實現信號和槽的通信 10 public: 11 tcpclientsocket(QObject *parent=0); 12 13 signals: 14 void updateClients(QString ,int); 15 void disconnected(int); 16 17 protected slots: 18 void dataReceived(); 19 void slotDisconnected(); 20 }; 21 22 #endif // TCPCLIENTSOCKET_H
- tcpclientsocket.cpp
1 #include "tcpclientsocket.h" 2 #include <QDebug> 3 4 tcpclientsocket::tcpclientsocket(QObject *parent) 5 { 6 //指定信號與槽的連接關系 7 //readyRead()是QIODevice的signal,由QTcpSocket繼承而來.QIODevice 8 //是所有輸入/輸出設備的一個抽象類,其中定義了基本的接口,在Qt中,QTcpSocket也被 9 //看做一個QIODevice,readyRead()信號在有數據到來時發出 10 connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived())); 11 //信號在斷開連接時發出 12 connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected())); 13 } 14 15 //當有數據到來的時候觸發dataReceived()函數,從套接字中將有效數據取出,然后 16 //發出updateClients()信號. 17 //updateClients()信號是通知服務器向聊天室內的所有成員廣播信息 18 void tcpclientsocket::dataReceived() 19 { 20 qDebug() << "accept message" << endl; 21 while(bytesAvailable()>0) 22 { 23 int length = bytesAvailable(); 24 char buf[1024]; 25 read(buf,length); 26 27 qDebug() << buf << endl; 28 QString msg=buf; 29 qDebug() << msg << endl; 30 emit updateClients(msg,length); 31 } 32 } 33 34 //槽函數slotDisconnected 35 void tcpclientsocket::slotDisconnected() 36 { 37 emit disconnected(this->socketDescriptor()); 38 }
客戶端
- tcpclient.h
1 #ifndef TCPCLIENT_H 2 #define TCPCLIENT_H 3 4 #include <QDialog> 5 6 namespace Ui { 7 class TcpClient; 8 } 9 10 #include <QDialog> 11 #include <QListWidget> 12 #include <QLineEdit> 13 #include <QPushButton> 14 #include <QLabel> 15 #include <QGridLayout> 16 17 #include <QHostAddress> 18 #include <QTcpSocket> 19 20 class TcpClient : public QDialog 21 { 22 Q_OBJECT 23 24 public: 25 explicit TcpClient(QWidget *parent = 0); 26 ~TcpClient(); 27 28 private: 29 Ui::TcpClient *ui; 30 QListWidget *contentListWidget; 31 QLineEdit *sendLineEdit; 32 QPushButton *sendBtn; 33 QLabel *userNameLabel; 34 QLineEdit *userNameLineEdit; 35 QLabel *serverIPLabel; 36 QLineEdit *serverIPLineEdit; 37 QLabel *portLabel; 38 QLineEdit *portLineEdit; 39 QPushButton *enterBtn; 40 QGridLayout *mainLayout; 41 42 private: 43 bool status; 44 int port; 45 QHostAddress *serverIP; 46 QString userName; 47 QTcpSocket *tcpSocket; 48 49 private slots: 50 void slotEnter(); 51 void slotConnected(); 52 void slotDisconnected(); 53 void dataReceived(); 54 void slotSend(); 55 56 57 }; 58 59 #endif // TCPCLIENT_H
- tcpclient.cpp
1 #include "tcpclient.h" 2 #include "ui_tcpclient.h" 3 4 #include <QMessageBox> 5 #include <QHostInfo> 6 7 TcpClient::TcpClient(QWidget *parent) : 8 QDialog(parent), 9 ui(new Ui::TcpClient) 10 { 11 ui->setupUi(this); 12 setWindowTitle(tr("TCP Client")); 13 14 contentListWidget = new QListWidget; 15 16 sendLineEdit = new QLineEdit; 17 sendBtn = new QPushButton(tr("發送")); 18 19 userNameLabel=new QLabel(tr("用戶名:")); 20 userNameLineEdit = new QLineEdit; 21 22 serverIPLabel = new QLabel(tr("服務器地址: ")); 23 serverIPLineEdit = new QLineEdit; 24 25 portLabel = new QLabel(tr("端口: ")); 26 portLineEdit = new QLineEdit; 27 28 enterBtn = new QPushButton(tr("進入聊天室")); 29 30 mainLayout = new QGridLayout(this); 31 mainLayout->addWidget(contentListWidget,0,0,1,2); 32 mainLayout->addWidget(sendLineEdit,1,0); 33 mainLayout->addWidget(sendBtn,1,1); 34 mainLayout->addWidget(userNameLabel,2,0); 35 mainLayout->addWidget(userNameLineEdit,2,1); 36 mainLayout->addWidget(serverIPLabel,3,0); 37 mainLayout->addWidget(serverIPLineEdit,3,1); 38 mainLayout->addWidget(portLabel,4,0); 39 mainLayout->addWidget(portLineEdit,4,1); 40 mainLayout->addWidget(enterBtn,5,0,1,2); 41 42 status = false; 43 44 port = 8010; 45 46 portLineEdit->setText(QString::number(port)); 47 48 serverIP=new QHostAddress(); 49 50 connect(enterBtn,SIGNAL(clicked(bool)),this,SLOT(slotEnter())); 51 connect(sendBtn,SIGNAL(clicked(bool)),this,SLOT(slotSend())); 52 53 sendBtn->setEnabled(false); 54 } 55 56 TcpClient::~TcpClient() 57 { 58 delete ui; 59 } 60 61 void TcpClient::slotEnter() 62 { 63 //status表示當前的狀態,true表示已經進入聊天室,false表示已經離開聊天室 64 //這里根據status的狀態決定是進入還是離開操作 65 if(!status) 66 { 67 //完成輸入合法性檢驗 68 QString ip = serverIPLineEdit->text(); 69 //用來判斷給定的IP地址是否能夠被正確解析 70 if(!serverIP->setAddress(ip)) 71 { 72 QMessageBox::information(this,tr("error"),tr("server ip address error!")); 73 return; 74 } 75 76 if(userNameLineEdit->text()=="") 77 { 78 QMessageBox::information(this,tr("error"),tr("User name error!")); 79 return; 80 } 81 82 userName = userNameLineEdit->text(); 83 84 //創建QTcpSocket類對象,並將信號/槽連接起來 85 tcpSocket = new QTcpSocket(this); 86 connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected())); 87 connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected())); 88 connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived())); 89 90 //與TCP服務器端連接,連接成功后發出connected 91 tcpSocket->connectToHost(*serverIP,port); 92 93 status = true; 94 } 95 else 96 { 97 int length = 0; 98 //構建一條離開聊天室的消息 99 QString msg = userName + tr(":Leave Chat Room"); 100 //通知服務器端以上構造的消息 101 if( ( length=tcpSocket->write( msg.toLatin1(),msg.length() ) )!=msg.length()) 102 { 103 return; 104 } 105 106 //與服務器端口連接,斷開后發出disconnected()信號 107 tcpSocket->disconnectFromHost(); 108 109 //將status狀態復位 110 status = false; 111 } 112 } 113 114 //當服務器連上成功后,客戶端構造一條進入聊天室的消息,並通知服務器 115 void TcpClient::slotConnected() 116 { 117 qDebug() << "進入服務器" << endl; 118 sendBtn->setEnabled(true); 119 enterBtn->setText(tr("離開")); 120 121 int length=0; 122 123 QString msg = userName+tr("Enter Chat Room"); 124 if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length()) 125 { 126 qDebug() << "發送失敗" << endl; 127 return; 128 } 129 else 130 { 131 qDebug() << "發送成功" << endl; 132 } 133 } 134 135 void TcpClient::slotDisconnected() 136 { 137 sendBtn->setEnabled(false); 138 enterBtn->setText(tr("進入聊天室")); 139 } 140 141 //當有數據到來時觸發此函數,從套接字中將有效數據提出並顯示 142 void TcpClient::dataReceived() 143 { 144 while(tcpSocket->bytesAvailable()>0) 145 { 146 QByteArray datagram; 147 datagram.resize(tcpSocket->bytesAvailable()); 148 149 tcpSocket->read(datagram.data(),datagram.size()); 150 151 QString msg = datagram.data(); 152 contentListWidget->addItem(msg.left(datagram.size())); 153 } 154 } 155 156 void TcpClient::slotSend() 157 { 158 if(sendLineEdit->text()=="") 159 { 160 return; 161 } 162 163 QString msg=userName+":"+sendLineEdit->text(); 164 165 tcpSocket->write(msg.toLatin1(),msg.length()); 166 sendLineEdit->clear(); 167 }
- main.cpp
1 #include "tcpclient.h" 2 #include <QApplication> 3 4 int main(int argc, char *argv[]) 5 { 6 QApplication a(argc, argv); 7 TcpClient w; 8 w.show(); 9 10 return a.exec(); 11 }
4 網頁瀏覽實例
首先創建一個QNetworkAccessManager類的實例,它用來發送網絡請求和接收應答.然后關聯了管理器的finished信號和自定義的槽,每當網絡應答結束時都會發射這個信號.最后使用了get函數來發送一個網絡請求,網絡請求使用QNetwrokRequest類表示,get()函數返回一個QNetworkReply對象
- mainwindow.h
1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QMainWindow> 5 6 #include <QNetworkReply> 7 #include <QNetworkAccessManager> 8 class QNetworkAccessManager; 9 10 namespace Ui { 11 class MainWindow; 12 } 13 14 class MainWindow : public QMainWindow 15 { 16 Q_OBJECT 17 18 public: 19 explicit MainWindow(QWidget *parent = 0); 20 ~MainWindow(); 21 22 private slots: 23 void replyFinished(QNetworkReply *); 24 25 26 private: 27 Ui::MainWindow *ui; 28 29 QNetworkAccessManager *manager; 30 }; 31 32 #endif // MAINWINDOW_H
- mainwindow.cpp
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 #include <QtNetwork> 5 6 7 MainWindow::MainWindow(QWidget *parent) : 8 QMainWindow(parent), 9 ui(new Ui::MainWindow) 10 { 11 ui->setupUi(this); 12 13 //創建QNetworkAccessManager類的實例,它用來發送網絡請求和接收應答.然后 14 //管理了管理器的finished()信號和自定義的槽,每當網絡應答結束時都會發射 15 //這個信號.最后使用了get()函數來發送一個網絡請求,網絡請求使用QNetworkRequest 16 //類表示,get()函數返回一個QNetworkReply對象 17 manager = new QNetworkAccessManager(this); 18 connect(manager,SIGNAL(finished(QNetworkReply*)),this, 19 SLOT(replyFinished(QNetworkReply*))); 20 manager->get(QNetworkRequest(QUrl("http://www.baidu.com"))); 21 } 22 23 MainWindow::~MainWindow() 24 { 25 delete ui; 26 } 27 28 void MainWindow::replyFinished(QNetworkReply *reply) 29 { 30 QString all = reply->readAll(); 31 ui->textBrowser->setText(all); 32 reply->deleteLater(); 33 }
- main.cpp
1 #include "mainwindow.h" 2 #include <QApplication> 3 4 int main(int argc, char *argv[]) 5 { 6 QApplication a(argc, argv); 7 MainWindow w; 8 w.show(); 9 10 return a.exec(); 11 }
- 文件下載示例
mianwindow.h
1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QMainWindow> 5 6 #include <QNetworkReply> 7 #include <QNetworkAccessManager> 8 class QNetworkAccessManager; 9 10 #include <QUrl> 11 class QFile; 12 13 namespace Ui { 14 class MainWindow; 15 } 16 17 class MainWindow : public QMainWindow 18 { 19 Q_OBJECT 20 21 public: 22 explicit MainWindow(QWidget *parent = 0); 23 ~MainWindow(); 24 25 void startRequest(QUrl url); 26 27 private slots: 28 void replyFinished(QNetworkReply *); 29 void httpFinished(); 30 void httpReadyRead(); 31 void updateDataReadProgress(qint64,qint64); 32 33 34 void on_pushButton_clicked(); 35 36 private: 37 Ui::MainWindow *ui; 38 39 QNetworkAccessManager *manager; 40 41 QNetworkReply *reply; 42 QUrl url; 43 QFile *file; 44 }; 45 46 #endif // MAINWINDOW_H
mainwindow.cpp
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 #include <QtNetwork> 5 6 7 MainWindow::MainWindow(QWidget *parent) : 8 QMainWindow(parent), 9 ui(new Ui::MainWindow) 10 { 11 ui->setupUi(this); 12 13 //創建QNetworkAccessManager類的實例,它用來發送網絡請求和接收應答.然后 14 //管理了管理器的finished()信號和自定義的槽,每當網絡應答結束時都會發射 15 //這個信號.最后使用了get()函數來發送一個網絡請求,網絡請求使用QNetworkRequest 16 //類表示,get()函數返回一個QNetworkReply對象 17 manager = new QNetworkAccessManager(this); 18 connect(manager,SIGNAL(finished(QNetworkReply*)),this, 19 SLOT(replyFinished(QNetworkReply*))); 20 // manager->get(QNetworkRequest(QUrl("http://www.baidu.com"))); 21 22 //ui->progressBar->hide(); 23 } 24 25 MainWindow::~MainWindow() 26 { 27 delete ui; 28 } 29 30 void MainWindow::startRequest(QUrl url) 31 { 32 //使用get()函數發送網絡請求 33 reply = manager->get(QNetworkRequest(url)); 34 //readyRead()信號繼承自QIODevice類,每當有新的數據可以讀取時,都會發射該信號 35 connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead())); 36 37 //每當網絡請求的下載進度更新時都會發射downloadProgress()信號,用於更新進度條; 38 connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this, 39 SLOT(updateDataReadProgress(qint64,qint64))); 40 41 //每當應答處理結束時,都會發射finished()信號 42 connect(reply,SIGNAL(finished()),this,SLOT(httpFinished())); 43 } 44 45 void MainWindow::replyFinished(QNetworkReply *reply) 46 { 47 QString all = reply->readAll(); 48 ui->textBrowser->setText(all); 49 reply->deleteLater(); 50 } 51 52 //完成下載后,重新隱藏進度條,刪除reply和file對象 53 void MainWindow::httpFinished() 54 { 55 ui->progressBar->hide(); 56 file->flush(); 57 file->close(); 58 reply->deleteLater(); 59 reply = 0; 60 delete file; 61 file = 0; 62 } 63 64 //首先判斷是否創建了文件,如果是,則讀取返回的所有數據,然后寫入文件中. 65 //該文件示后面的下載按鈕單機信號槽中創建並打開的 66 void MainWindow::httpReadyRead() 67 { 68 if(file) 69 { 70 file->write(reply->readAll()); 71 } 72 } 73 74 //設置進度條的最大值和當前值 75 void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) 76 { 77 ui->progressBar->setMaximum(totalBytes); 78 ui->progressBar->setValue(bytesRead); 79 } 80 81 //使用要下載的文件名創建了本地文件,使用輸入的url進行網絡請求,並顯示進度條 82 void MainWindow::on_pushButton_clicked() 83 { 84 url = ui->lineEdit->text(); 85 QFileInfo info(url.path()); 86 QString fileName(info.fileName()); 87 qDebug() << fileName<<endl; 88 file = new QFile(fileName); 89 90 if(!file->open(QIODevice::WriteOnly)) 91 { 92 qDebug()<<"file open error"; 93 delete file; 94 file = 0; 95 return; 96 } 97 startRequest(url); 98 ui->progressBar->setValue(0); 99 ui->progressBar->show(); 100 }