37.Qt网络与通信
阅读原文时间:2023年07月15日阅读:1

1  获取本机网络与通信

  在网络应用中,经常需要获得本机的主机名.IP地址和硬件地址等网络信息.运用QHostInfo,QNetWorkInterface,QNetworkAddressEntry可获得本机的网络信息.

  • widget.h

    #ifndef WIDGET_H
    #define WIDGET_H

    #include
    #include
    #include
    #include
    #include
    #include

    #include
    #include

    namespace Ui {
    class Widget;
    }

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = );
    ~Widget();

    private:
    QLabel *hostLabel;
    QLineEdit *LineEditLocalHostName;
    QLabel *ipLabel;
    QLineEdit *LineEditAddress;

     QPushButton \*detailBtn;
    
     QGridLayout \*mainLayout;

    private:
    Ui::Widget *ui;

    public:
    void getHostInformation();
    public slots:
    void slotDetail();
    };

    #endif // WIDGET_H

  • widget.cpp

    #include "widget.h"
    #include "ui_widget.h"

    Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
    {
    ui->setupUi(this);
    hostLabel = new QLabel(tr("主机名: "));
    LineEditLocalHostName = new QLineEdit;
    ipLabel = new QLabel(tr("IP 地址:"));
    LineEditAddress = new QLineEdit;

     detailBtn = new QPushButton(tr("详细"));
    
     mainLayout = new QGridLayout(this);  
     mainLayout->addWidget(hostLabel,,);  
     mainLayout->addWidget(LineEditLocalHostName,,);  
     mainLayout->addWidget(ipLabel,,);  
     mainLayout->addWidget(LineEditAddress,,);  
     //第二行第0个,占两列  
     mainLayout->addWidget(detailBtn,,,,);
    
     getHostInformation();  
     connect(detailBtn,SIGNAL(clicked(bool)),this,SLOT(slotDetail()));  

    }

    Widget::~Widget()
    {
    delete ui;
    }

    void Widget::getHostInformation()
    {
    //获得本机主机名.QHostInfo提供了一系列有关网络信息的静态函数,
    //可以根据主机名获得分配的IP地址,也可以根据IP地址获得相应的主机名
    **37 QString localHostName = QHostInfo::localHostName();
    ** LineEditLocalHostName->setText(localHostName);

     //根据主机名获得相关主机信息,包括IP地址等.  
     //QHostInfo::fromName()函数通过主机名查找IP地址信息  

    42 QHostInfo hostInfo = QHostInfo::fromName(localHostName);
    //获得主机的IP地址列表
    QList listAddress = hostInfo.addresses();

     //在不为空的情况下,使用第一个IP地址  
     if(!listAddress.isEmpty())  
     {  
         LineEditAddress->setText(listAddress.first().toString());  
     }  

    }

    void Widget::slotDetail()
    {
    QString detail="";
    //QNetworkInterface类提供了一个IP地址和网络接口的列表
    QList list=QNetworkInterface::allInterfaces();

     for(int i=;i<list.count();i++)  
     {  
         QNetworkInterface interface=list.at(i);
     //获得网络接口的名称  
     **detail=detail+tr("设备: ")+interface.name()+"\\n";  </code></pre>

    ** //获得网络接口的名称
    detail=detail+tr("硬件地址:")+interface.hardwareAddress()+"\n";
    //每个网络接口包括0个或多个IP地址,
    //每个IP地址有选择性地与一个子网掩码和一个广播地址相关联
    //QNetworkAddressEntry类存储了被网络接口支持的一个IP地址,
    //同时还包括与之相关的子网掩码和广播地址
    **73 QList entryList=interface.addressEntries();
    **

         for(int j=;j<entryList.count();j++)  
         {  
             QNetworkAddressEntry entry = entryList.at(j);  
             detail=detail+"\\t"+tr("IP地址: ")+entry.ip().toString()+"\\n";  
             detail=detail+"\\t"+tr("子网掩码: ")+entry.netmask().toString()+"\\n";  
             detail=detail+"\\t"+tr("广播地址: ")+entry.broadcast().toString()+"\\n";  
         }  
         QMessageBox::information(this,tr("Detail"),detail);  
     }  

    }

  • main.cpp

    #include "widget.h"
    #include

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget w;
    w.show();

     return a.exec();  

    }


2  基于UDP的网络广播程序

  2.1  UDP(user data protocol)是一种简单轻量级,不可靠,面向数据报无连接的传输协议,可以用在不是十分重要的场合

  2.2  UDP编程模型

  在UDP方式下客户端并不与服务器建立连接,它只负责调用发送函数向服务器法术数据报.类似的服务器不从客户端接收连接,只负责调用接收函数,等待来自某客户端的数据到达.Qt中通过QUdpSocket类实现UDP协议的编程.

服务器端:

  • udpserver.h

    #ifndef UDPSERVER_H
    #define UDPSERVER_H

    #include
    #include
    #include
    #include
    #include
    #include
    #include

    namespace Ui {
    class UdpServer;
    }

    class UdpServer : public QDialog
    {
    Q_OBJECT

    public:
    explicit UdpServer(QWidget *parent = ,Qt::WindowFlags f=);
    ~UdpServer();

    public slots:
    void StartBtnClicked();
    void timeout();

    private:
    int port;
    bool isStarted;
    QUdpSocket *udpSocket;
    QTimer *timer;

    private:
    QLabel *TimerLabel;
    QLineEdit *TextLineEdit;
    QPushButton *StartBtn;
    QVBoxLayout *mainLayout;

    private:
    Ui::UdpServer *ui;

    };

    #endif // UDPSERVER_H

  • udpserver.cpp

    #include "udpserver.h"
    #include "ui_udpserver.h"

    #include

    UdpServer::UdpServer(QWidget *parent,Qt::WindowFlags f) :
    QDialog(parent,f),
    ui(new Ui::UdpServer)
    {
    ui->setupUi(this);

     setWindowTitle(tr("UDP 服务器"));
    
     TimerLabel = new QLabel(tr("计时器:"),this);  
     TextLineEdit = new QLineEdit(this);  
     StartBtn = new QPushButton(tr("开始"),this);
    
     //设置垂直布局  
     mainLayout = new QVBoxLayout(this);  
     mainLayout->addWidget(TimerLabel);  
     mainLayout->addWidget(TextLineEdit);  
     mainLayout->addWidget(StartBtn);
    
     connect(StartBtn,SIGNAL(clicked(bool)),this,SLOT(StartBtnClicked()));
    
     //设置UDP的端口号参数,服务器定时向此端口发送广播消息  
     port = ;  
     isStarted = false;  
     udpSocket = new QUdpSocket(this);  
     //创建定时器  
     timer = new QTimer(this);  
     //定时发送广播消息  
     connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));  

    }

    UdpServer::~UdpServer()
    {
    delete ui;
    }

    void UdpServer::StartBtnClicked()
    {
    //打开
    if(!isStarted)
    {
    StartBtn->setText(tr("停止"));
    //每隔1000秒发送一个消息
    timer->start();
    isStarted=true;
    }
    else
    {
    StartBtn->setText(tr("开始"));
    isStarted = false;
    timer->stop();
    }
    }

    void UdpServer::timeout()
    {
    QString msg = TextLineEdit->text();
    int length=;
    if(msg=="")
    {
    return;
    }

     //QHostAddress::Broadcast 指定向广播地址发送  
     if(length=udpSocket->writeDatagram(msg.toLatin1(),  
                msg.length(),QHostAddress::Broadcast,port)!=msg.length())  
     {  
         return;  
     }  

    }

  • udpclient.h

    #ifndef UDPCLIENT_H
    #define UDPCLIENT_H

    #include
    #include
    #include
    #include
    #include

    namespace Ui {
    class UdpClient;
    }

    class UdpClient : public QDialog
    {
    Q_OBJECT

    public:
    explicit UdpClient(QWidget *parent = );
    ~UdpClient();

    public slots:
    void CloseBtnClicked();
    void dataReceived();

    private:
    int port;
    QUdpSocket *udpSocket;

    private:
    Ui::UdpClient *ui;
    QTextEdit *ReceiveTextEdit;
    QPushButton *closeBtn;
    QVBoxLayout *mainLayout;
    };

    #endif // UDPCLIENT_H

  • udpclient.cpp

    #include "udpclient.h"
    #include "ui_udpclient.h"
    #include
    #include

    UdpClient::UdpClient(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::UdpClient)
    {
    ui->setupUi(this);

     setWindowTitle(tr("UDP 客户端"));
    
     ReceiveTextEdit = new QTextEdit(this);
    
     closeBtn = new QPushButton(tr("关闭"),this);
    
     mainLayout = new QVBoxLayout(this);  
     mainLayout->addWidget(ReceiveTextEdit);  
     mainLayout->addWidget(closeBtn);
    
     connect(closeBtn,SIGNAL(clicked(bool)),this,SLOT(CloseBtnClicked()));
    
     //设置UDP的端口号参数,指定在此端口上监听数据  
     port = ;
    
     //创建一个QUdpSocket  
     udpSocket = new QUdpSocket(this);  
     //连接QIODevice的readyRead()信号  
     //QUdpSocket也是一个I/O设备,从QIODevice继承而来,当有数据到达I/O设备时,发出readyRead()信号  
     connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    
     //绑定到指定的端口上  
     bool result=udpSocket->bind(port);
    
     if(!result)  
     {  
         QMessageBox::information(this,tr("error"),tr("udp socket create error!"));  
         return;  
     }  

    }

    UdpClient::~UdpClient()
    {
    delete ui;
    }

    void UdpClient::CloseBtnClicked()
    {
    close();
    }

    void UdpClient::dataReceived()
    {
    //判断UdpSocket中是否有数据报可读
    //hasPendingDatagrams()方法在至少有一个数据报可读时返回true
    while(udpSocket->hasPendingDatagrams())
    {
    //实现读取第一个数据报
    //pendingDataSize()可以获得第一个数据报的长度
    QByteArray datagram;
    datagram.resize(udpSocket->pendingDatagramSize());
    udpSocket->readDatagram(datagram.data(),datagram.size());

         QString msg = datagram.data();  
         //显示数据内容  
         ReceiveTextEdit->insertPlainText(msg);  
     }  

    }


3  基于TCP的网络聊天室程序

  TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地送达网络上的其他计算机.因此,对可靠性要求高的数据通信系统往往使用TCP协议传输数据,但在正则收发数据前通信双方必须首先建立连接.

  首先启动服务器,一段时间后启动客户端,它与此服务器经过三次握手后建立连接.此后的一段时间内,客户端向服务器发送一个请求,服务器处理这个请求,并为客户端发回一个响应.这个过程一直持续下去,知道客户端为服务器发一个文件结束符,并关闭客户端连接,接着服务器也关闭服务器的连接,结束运行或等待一个新的客户端连接.

  Qt中通过QTcpSocket类实现TCP协议的编程.

代码示例:

服务器端

  • tcpserver.h

    #ifndef TCPSERVER_H
    #define TCPSERVER_H

    #include
    #include
    #include
    #include
    #include
    #include
    #include "serverh.h"

    namespace Ui {
    class TcpServer;
    }

    class TcpServer : public QDialog
    {
    Q_OBJECT

    public:
    explicit TcpServer(QWidget *parent = );
    ~TcpServer();

    private:
    Ui::TcpServer *ui;
    QListWidget *ContentListWidget;
    QLabel *PortLabe;
    QLineEdit *PortLineEdit;
    QPushButton *CreateBtn;
    QGridLayout *mainLayout;

    private:
    int port;
    serverh *server;

    public slots:
    void slotCreateServer();
    void updateServer(QString,int);

    };

    #endif // TCPSERVER_H

  • tcpserver.cpp

    #include "tcpserver.h"
    #include "ui_tcpserver.h"

    TcpServer::TcpServer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpServer)
    {
    ui->setupUi(this);

     setWindowTitle(tr("TCP Server"));
    
     ContentListWidget = new QListWidget;
    
     PortLabe = new QLabel(tr("端口: "));  
     PortLineEdit = new QLineEdit();
    
     CreateBtn = new QPushButton(tr("创建聊天室"));
    
     mainLayout=new QGridLayout(this);  
     mainLayout->addWidget(ContentListWidget,,,,);  
     mainLayout->addWidget(PortLabe,,);  
     mainLayout->addWidget(PortLineEdit,,);  
     mainLayout->addWidget(CreateBtn,,,,);
    
     port=;  
     PortLineEdit->setText(QString::number(port));
    
     connect(CreateBtn,SIGNAL(clicked(bool)),this,SLOT(slotCreateServer()));  

    }

    TcpServer::~TcpServer()
    {
    delete ui;
    }

    void TcpServer::slotCreateServer()
    {
    //创建一个serverh对象
    server = new serverh(this,port);
    //将serverh对象的updateServer()信号与相应的槽函数进行连接
    connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));

     CreateBtn->setEnabled(false);  

    }

    void TcpServer::updateServer(QString msg , int length)
    {
    ContentListWidget->addItem(msg.left(length));
    }

  • server.h

    #ifndef SERVERH_H
    #define SERVERH_H

    #include
    #include

    #include "tcpclientsocket.h"//包含TCP的套接字

    class serverh : public QTcpServer
    {
    Q_OBJECT
    public:
    serverh(QObject *parent=,int port=);
    //用来保存与每一个客户端连接的TcpClientSocket
    QList tcpClientSocketList;

    signals:
    void updateServer(QString,int);

    public slots:
    void updateClients(QString,int);
    void slotDisconnected(int);

    protected:
    void incomingConnection(int socketDescriptor);
    };

    #endif // SERVERH_H

  • server.cpp

    #include "serverh.h"

    serverh::serverh(QObject *parent,int port):QTcpServer(parent)
    {
    //在指定的端口对任意地址进行监听
    //QHostAddress定义了几种特殊的IP地址
    //QHostAddress定义了几种特殊的IP地址,QHostAddress::Null表示一个空的地址
    //QHostAddress::LocalHost表示IPV4的本机地址127.0.0.1
    //QHostAddress::LocalHostIPV6表示IPv6的本机地址
    //QHostAddress::Broadcast表示广播地址255.255.255.255
    //QHostAddress::Any表示Ipv4的任意地址0.0.0.0
    //QHostAddress::AnyIPv6表示IPv6的任意地址
    listen(QHostAddress::Any,port);
    }

    //当出现一个新的连接时,QTcpServer触发incomingConnection()函数,参数
    //socketDescriptor指定连接的Socket描述符
    void serverh::incomingConnection(int socketDescriptor)
    {
    qDebug() << "receive connect" << endl;
    //创建一个新的TcpClientSocket客户端通信
    tcpclientsocket *tcpClientSocket = new tcpclientsocket(this);
    //连接TcpClientSocket的updateClients信号
    connect(tcpClientSocket,SIGNAL(updateClients(QString,int)),this,
    SLOT(updateClients(QString,int)));
    //连接TcpClientSocket的disconnect信号
    connect(tcpClientSocket,SIGNAL(disconnected(int)),this,
    SLOT(slotDisconnected(int)));

     //将tcpClient加入客户端套接字列表以便管理  
     tcpClientSocket->setSocketDescriptor(socketDescriptor);
    
     tcpClientSocketList.append(tcpClientSocket);  

    }

    void serverh::updateClients(QString msg, int length)
    {
    //发出updateServer信号,来通知服务器对话框更新相应的显示状态
    qDebug() << msg << endl; emit updateServer(msg,length); qDebug() << msg << endl; for(int i=;iwrite(msg.toLatin1(),length)!=length)
    {
    continue;
    }
    }
    }

    void serverh::slotDisconnected(int descriptor)
    {
    for(int i=;i<tcpClientSocketList.count();i++)
    {
    QTcpSocket *item = tcpClientSocketList.at(i);

         if(item->socketDescriptor()==descriptor)  
         {  
             tcpClientSocketList.removeAt(i);  
             return;  
         }  
     }  
     return;  

    }

  • tcpclientsocket.h

    #ifndef TCPCLIENTSOCKET_H
    #define TCPCLIENTSOCKET_H

    #include
    #include

    class tcpclientsocket : public QTcpSocket
    {
    Q_OBJECT //添加宏是为了实现信号和槽的通信
    public:
    tcpclientsocket(QObject *parent=);

    signals:
    void updateClients(QString ,int);
    void disconnected(int);

    protected slots:
    void dataReceived();
    void slotDisconnected();
    };

    #endif // TCPCLIENTSOCKET_H

  • tcpclientsocket.cpp

    #include "tcpclientsocket.h"
    #include

    tcpclientsocket::tcpclientsocket(QObject *parent)
    {
    //指定信号与槽的连接关系
    //readyRead()是QIODevice的signal,由QTcpSocket继承而来.QIODevice
    //是所有输入/输出设备的一个抽象类,其中定义了基本的接口,在Qt中,QTcpSocket也被
    //看做一个QIODevice,readyRead()信号在有数据到来时发出
    connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    //信号在断开连接时发出
    connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
    }

    //当有数据到来的时候触发dataReceived()函数,从套接字中将有效数据取出,然后
    //发出updateClients()信号.
    //updateClients()信号是通知服务器向聊天室内的所有成员广播信息
    void tcpclientsocket::dataReceived()
    {
    qDebug() << "accept message" << endl; while(bytesAvailable()>)
    {
    int length = bytesAvailable();
    char buf[];
    read(buf,length);

         qDebug() << buf << endl;  
         QString msg=buf;  
         qDebug() << msg << endl;  
         emit updateClients(msg,length);  
     }  

    }

    //槽函数slotDisconnected
    void tcpclientsocket::slotDisconnected()
    {
    emit disconnected(this->socketDescriptor());
    }

客户端

  • tcpclient.h

    #ifndef TCPCLIENT_H
    #define TCPCLIENT_H

    #include

    namespace Ui {
    class TcpClient;
    }

    #include
    #include
    #include
    #include
    #include
    #include

    #include
    #include

    class TcpClient : public QDialog
    {
    Q_OBJECT

    public:
    explicit TcpClient(QWidget *parent = );
    ~TcpClient();

    private:
    Ui::TcpClient *ui;
    QListWidget *contentListWidget;
    QLineEdit *sendLineEdit;
    QPushButton *sendBtn;
    QLabel *userNameLabel;
    QLineEdit *userNameLineEdit;
    QLabel *serverIPLabel;
    QLineEdit *serverIPLineEdit;
    QLabel *portLabel;
    QLineEdit *portLineEdit;
    QPushButton *enterBtn;
    QGridLayout *mainLayout;

    private:
    bool status;
    int port;
    QHostAddress *serverIP;
    QString userName;
    QTcpSocket *tcpSocket;

    private slots:
    void slotEnter();
    void slotConnected();
    void slotDisconnected();
    void dataReceived();
    void slotSend();

    };

    #endif // TCPCLIENT_H

  • tcpclient.cpp

    #include "tcpclient.h"
    #include "ui_tcpclient.h"

    #include
    #include

    TcpClient::TcpClient(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpClient)
    {
    ui->setupUi(this);
    setWindowTitle(tr("TCP Client"));

     contentListWidget = new QListWidget;
    
     sendLineEdit = new QLineEdit;  
     sendBtn = new QPushButton(tr("发送"));
    
     userNameLabel=new QLabel(tr("用户名:"));  
     userNameLineEdit = new QLineEdit;
    
     serverIPLabel = new QLabel(tr("服务器地址: "));  
     serverIPLineEdit = new QLineEdit;
    
     portLabel = new QLabel(tr("端口: "));  
     portLineEdit = new QLineEdit;
    
     enterBtn = new QPushButton(tr("进入聊天室"));
    
     mainLayout = new QGridLayout(this);  
     mainLayout->addWidget(contentListWidget,,,,);  
     mainLayout->addWidget(sendLineEdit,,);  
     mainLayout->addWidget(sendBtn,,);  
     mainLayout->addWidget(userNameLabel,,);  
     mainLayout->addWidget(userNameLineEdit,,);  
     mainLayout->addWidget(serverIPLabel,,);  
     mainLayout->addWidget(serverIPLineEdit,,);  
     mainLayout->addWidget(portLabel,,);  
     mainLayout->addWidget(portLineEdit,,);  
     mainLayout->addWidget(enterBtn,,,,);
    
     status = false;
    
     port = ;
    
     portLineEdit->setText(QString::number(port));
    
     serverIP=new QHostAddress();
    
     connect(enterBtn,SIGNAL(clicked(bool)),this,SLOT(slotEnter()));  
     connect(sendBtn,SIGNAL(clicked(bool)),this,SLOT(slotSend()));
    
     sendBtn->setEnabled(false);  

    }

    TcpClient::~TcpClient()
    {
    delete ui;
    }

    void TcpClient::slotEnter()
    {
    //status表示当前的状态,true表示已经进入聊天室,false表示已经离开聊天室
    //这里根据status的状态决定是进入还是离开操作
    if(!status)
    {
    //完成输入合法性检验
    QString ip = serverIPLineEdit->text();
    //用来判断给定的IP地址是否能够被正确解析
    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-&gt;text();
    
     //创建QTcpSocket类对象,并将信号/槽连接起来  
     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()));
    
     //与TCP服务器端连接,连接成功后发出connected  
     tcpSocket-&gt;connectToHost(\*serverIP,port);
    
     status = true;  
    } else { int length = ; //构建一条离开聊天室的消息 QString msg = userName + tr(":Leave Chat Room"); //通知服务器端以上构造的消息 if( ( length=tcpSocket->write( msg.toLatin1(),msg.length() ) )!=msg.length()) { return; }
     //与服务器端口连接,断开后发出disconnected()信号  
     tcpSocket-&gt;disconnectFromHost();
    
     //将status状态复位  
     status = false;  
    }

    }

    //当服务器连上成功后,客户端构造一条进入聊天室的消息,并通知服务器
    void TcpClient::slotConnected()
    {
    qDebug() << "进入服务器" << endl; sendBtn->setEnabled(true);
    enterBtn->setText(tr("离开"));

     int length=;
    
     QString msg = userName+tr("Enter Chat Room");  
     if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())  
     {  
         qDebug() << "发送失败" << endl;  
         return;  
     }  
     else  
     {  
         qDebug() << "发送成功" << endl;  
     }  

    }

    void TcpClient::slotDisconnected()
    {
    sendBtn->setEnabled(false);
    enterBtn->setText(tr("进入聊天室"));
    }

    //当有数据到来时触发此函数,从套接字中将有效数据提出并显示
    void TcpClient::dataReceived()
    {
    while(tcpSocket->bytesAvailable()>)
    {
    QByteArray datagram;
    datagram.resize(tcpSocket->bytesAvailable());

         tcpSocket->read(datagram.data(),datagram.size());
     QString msg = datagram.data();  
     contentListWidget-&gt;addItem(msg.left(datagram.size()));  
    }

    }

    void TcpClient::slotSend()
    {
    if(sendLineEdit->text()=="")
    {
    return;
    }

     QString msg=userName+":"+sendLineEdit->text();
    
     tcpSocket->write(msg.toLatin1(),msg.length());  
     sendLineEdit->clear();  

    }

  • main.cpp

    #include "tcpclient.h"
    #include

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    TcpClient w;
    w.show();

     return a.exec();  

    }


4  网页浏览实例

  首先创建一个QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后关联了管理器的finished信号和自定义的槽,每当网络应答结束时都会发射这个信号.最后使用了get函数来发送一个网络请求,网络请求使用QNetwrokRequest类表示,get()函数返回一个QNetworkReply对象

  • mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include

    #include
    #include
    class QNetworkAccessManager;

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = );
    ~MainWindow();

    private slots:
    void replyFinished(QNetworkReply *);

    private:
    Ui::MainWindow *ui;

     QNetworkAccessManager \*manager;  

    };

    #endif // MAINWINDOW_H

  • mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    #include

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

     //创建QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后  
     //管理了管理器的finished()信号和自定义的槽,每当网络应答结束时都会发射  
     //这个信号.最后使用了get()函数来发送一个网络请求,网络请求使用QNetworkRequest  
     //类表示,get()函数返回一个QNetworkReply对象  
     manager = new QNetworkAccessManager(this);  
     connect(manager,SIGNAL(finished(QNetworkReply\*)),this,  
             SLOT(replyFinished(QNetworkReply\*)));  
     manager->get(QNetworkRequest(QUrl("http://www.baidu.com")));  

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::replyFinished(QNetworkReply *reply)
    {
    QString all = reply->readAll();
    ui->textBrowser->setText(all);
    reply->deleteLater();
    }

  • main.cpp

    #include "mainwindow.h"
    #include

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

     return a.exec();  

    }


  • 文件下载示例

mianwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

#include
#include
class QNetworkAccessManager;

#include
class QFile;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = );
~MainWindow();

 void startRequest(QUrl url);

private slots:
void replyFinished(QNetworkReply *);
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64,qint64);

 void on\_pushButton\_clicked();

private:
Ui::MainWindow *ui;

 QNetworkAccessManager \*manager;

 QNetworkReply \*reply;  
 QUrl url;  
 QFile \*file;  

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

 //创建QNetworkAccessManager类的实例,它用来发送网络请求和接收应答.然后  
 //管理了管理器的finished()信号和自定义的槽,每当网络应答结束时都会发射  
 //这个信号.最后使用了get()函数来发送一个网络请求,网络请求使用QNetworkRequest  
 //类表示,get()函数返回一个QNetworkReply对象  
 manager = new QNetworkAccessManager(this);  
 connect(manager,SIGNAL(finished(QNetworkReply\*)),this,  
         SLOT(replyFinished(QNetworkReply\*)));  

// manager->get(QNetworkRequest(QUrl("http://www.baidu.com")));

 //ui->progressBar->hide();  

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::startRequest(QUrl url)
{
//使用get()函数发送网络请求
reply = manager->get(QNetworkRequest(url));
//readyRead()信号继承自QIODevice类,每当有新的数据可以读取时,都会发射该信号
connect(reply,SIGNAL(readyRead()),this,SLOT(httpReadyRead()));

 //每当网络请求的下载进度更新时都会发射downloadProgress()信号,用于更新进度条;  
 connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,  
         SLOT(updateDataReadProgress(qint64,qint64)));

 //每当应答处理结束时,都会发射finished()信号  
 connect(reply,SIGNAL(finished()),this,SLOT(httpFinished()));  

}

void MainWindow::replyFinished(QNetworkReply *reply)
{
QString all = reply->readAll();
ui->textBrowser->setText(all);
reply->deleteLater();
}

//完成下载后,重新隐藏进度条,删除reply和file对象
void MainWindow::httpFinished()
{
ui->progressBar->hide();
file->flush();
file->close();
reply->deleteLater();
reply = ;
delete file;
file = ;
}

//首先判断是否创建了文件,如果是,则读取返回的所有数据,然后写入文件中.
//该文件示后面的下载按钮单机信号槽中创建并打开的
void MainWindow::httpReadyRead()
{
if(file)
{
file->write(reply->readAll());
}
}

//设置进度条的最大值和当前值
void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}

//使用要下载的文件名创建了本地文件,使用输入的url进行网络请求,并显示进度条
void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
QFileInfo info(url.path());
QString fileName(info.fileName());
qDebug() << fileName<<endl;
file = new QFile(fileName);

 if(!file->open(QIODevice::WriteOnly))  
 {  
     qDebug()<<"file open error";  
     delete file;  
     file = ;  
     return;  
 }  
 startRequest(url);  
 ui->progressBar->setValue();  
 ui->progressBar->show();  

}