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()+"
    ";
    66         //获得网络接口的名称
    67         detail=detail+tr("硬件地址:")+interface.hardwareAddress()+"
    ";
    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+"	"+tr("IP地址: ")+entry.ip().toString()+"
    ";
    80             detail=detail+"	"+tr("子网掩码: ")+entry.netmask().toString()+"
    ";
    81             detail=detail+"	"+tr("广播地址: ")+entry.broadcast().toString()+"
    ";
    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 }
原文地址:https://www.cnblogs.com/xiaochi/p/8831465.html