37.Qt網絡與通信


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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM