Qt 网络模块提供了用于编写 TCP/IP 客户端和服务器端程序的各种类,如用于 TCP 通信的QTcpSocket 和 QTcpServer,用于 UDP 通信的 QUdpSocket,还有用于实现 HTTP、FTP 等普通网络协议的高级类如 QNetworkRequest,QNetworkReply 和QNetworkAccessManager。Qt 网络模块还提供用于网络代理、网络承载管理的类,提供基于安全套接字层(Secure Sockets Layer,SSL)协议的安全网络通信的类。
要在程序中使用 Qt 网络模块,需要在项目配置文件中增加一条配置语句:
Qt += network
1、QHostInfo 和 QNetworkInterface 类
查询一个主机的MAC地址或IP 地址是网络应用程序中经常用到的功能,Qt提供了QHostInfo和QNetworkInterface 类可以用于此类信息的查询。
QHostInfo 的静态函数 localHostName()可获取本机的主机名,静态函数 fromName()可以通过主机名获取IP 地址,静态函数 lookupHost()可以通过一个主机名,以异步方式查找这个主机的IP地址。下表是QHostInfo 类主要的功能函数(省略了函数中的const 关键字)。
类别 | 函数原型 | 作用 |
公共函数 | QList<QHostAddress> addresses() HostInfoError error() QString errorString() QString hostName() int lookupld() | 返回与 hostname()主机关联的IP 地址列表 如果主机查找失败,返回失败类型 如果主机查找失败,返回错误描述字符串 返回通过 IP查找的主机的名称 返回本次查找的ID |
静态函数 | void abortHostLookup(int id) QHostInfo fromName(QString &name) QString localDomainName() QString localHostName() int lookupHost(QString&name, QObiect*receiver,char *member) | 中断主机查找 返回指定的主机名的IP 地址 返回本机DNS域名 返回本机主机名 以异步方式根据主机名查找主机的 IP 地址,并返回一个表示本次查找的ID,可用于 abortHostLookup() |
QNetworkInterface 可以获得运行应用程序的主机的所有 IP 地址和网络接口列表。静态函数allInterfaces()返回主机上所有的网络接口的列表,一个网络接口可能包括多个的IP 地址,每个IP地址与掩码或广播地址关联。如果无需知道子网掩码和广播的IP 地址,使用静态函数 allAddresses()可以获得主机上的所有IP 地址列表。下表是QNetworkInterface 类的主要功能函数。
类别 | 函数原型 | 作用 |
公共函数 | QList<QNetworkAddressEntry> addressEntries() OString hardwareAddress() QString humanReadableName() bool isValid() QString name() | 返回该网络接口(包括子网掩码和广播地址)的IP 地址列表 返回该接口的低级硬件地址,以太网里就是 MAC 地址 返回可以读懂的接口名称,如果名称不确定,得到的就是name()函数的返回值 如果接口信息有效就返回 true 返回网络接口名称 |
静态函数 | QList<QHostAddress> allAddresses() QList<QNetworkInterface> allInterfaces() | 返回主机上所有 IP 地址的列表 返回主机上所有接口的网络列表 |
为演示这两个类的主要功能,创建一个窗口基于 QDialog 的应用程序实例运行时界面如下图所示。对话框界面由 UI设计器设计,主要代码都是各按钮的 clicked()信号的槽函数。
窗口上的“QHostInf 取本机主机名和I地址”按的响应代码如下:
void HostDialog::on_btnGetHostInfo_clicked()
{
QString hostName = QHostInfo::localHostName();
ui->textInfo->appendPlainText(("本机主机名称:") + hostName + "\n" );
QHostInfo hostInfo = QHostInfo::fromName(hostName);
QList<QHostAddress> addList = hostInfo.addresses();
if(addList.isEmpty())
{
return;
}
for(int i = 0; i < addList.count(); i++)
{
QHostAddress host = addList.at(i);
bool show = ui->chkOnlyIPv4->isChecked();
if(show)
{
show = (QAbstractSocket::IPv4Protocol == host.protocol());
}
else{
show = true;
}
if(show)
{
ui->textInfo->appendPlainText("协议:" + protocolName(host.protocol()));
ui->textInfo->appendPlainText("本机IP地址:" + host.toString());
ui->textInfo->appendPlainText("");
}
}
}
查找主机地址信息
QHostInfo 的静态函数 lokupHost()可以根据主机名、域名或 IP 地址查找主机的地址信息lookupHost()函数原型如下:
int QHostInfo::lookupHost(const QString &name, QObject *receiver, const char *member)
输入参数 name 是表示主机名的字符串,可以是一个主机名、一个域名,或者是一个IP 地址lookupHost()以异步方式查找主机地址,参数 receiver 和 member 指定一个响应槽函数的接收者和槽函数名称。执行 lookupHost()后,程序可能需要花一定时间来查找主机地址,但不会阻塞程序的运行。当查找到主机地址后,通过信号通知设定的槽函数,在槽函数里读取查找的结果。函数返回一个表示查找的ID。
窗口“OHostInfo 查找域名的IP 地址”按的槽函数及 lokupHost()函数关联槽函数代码如下:
void HostDialog::on_btnLookup_clicked()
{
QString hostname = ui->lineEdit->text();
ui->textInfo->appendPlainText("正在查找主机信息:" + hostname);
QHostInfo::lookupHost(hostname, this, SLOT(lookedUpHostInfo(QHostInfo)));
}
void HostDialog::lookedUpHostInfo(const QHostInfo &host)
{
QList<QHostAddress> addList = host.addresses();
if(addList.isEmpty())
{
return;
}
for(int i = 0; i < addList.count(); i++)
{
QHostAddress aHost = addList.at(i);
bool show = ui->chkOnlyIPv4->isChecked();
if(show)
{
show = QAbstractSocket::IPv4Protocol == aHost.protocol();
}
else{
show = true;
}
if(show)
{
ui->textInfo->appendPlainText("协议:" + protocolName(aHost.protocol()));
ui->textInfo->appendPlainText(aHost.toString());
}
}
}
QNetworkInterface 可以获得应用程序所在主机的所有网络接口,包括其子网码和广播地址等静态函数QNetworkInterface::allInterfaces()获取所有网络接口的列表,函数原型为:
QList<QNetworkInterface> QNetworkInterface::allInterfaces()
其返回结果是一个QNetworkInterface 类的列表。界面上“QNetworkInterface::allInterfaces()”按钮的响应代码如下:
void HostDialog::on_btnAllInterfaces_clicked()
{
QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
for(int i = 0; i < list.count(); i++)
{
QNetworkInterface interface = list.at(i);
if(!interface.isValid())
{
continue;
}
ui->textInfo->appendPlainText("设备名称:" + interface.humanReadableName());
ui->textInfo->appendPlainText("硬件地址:" + interface.hardwareAddress());
QList<QNetworkAddressEntry> entryList = interface.addressEntries();
for(int j = 0; j < entryList.count(); j++)
{
QNetworkAddressEntry entry = entryList.at(j);
ui->textInfo->appendPlainText("IP 地址:" + entry.ip().toString());
ui->textInfo->appendPlainText("子网掩码:" + entry.netmask().toString());
ui->textInfo->appendPlainText("广播地址:" + entry.broadcast().toString() + "\n");
ui->textInfo->appendPlainText("\n");
}
}
}
通过QNetworkInterface::allInterfaces()获取网络接口列表 list之后,显示每个接口的humanReadableName()和 hardwareAddress()。每个接口又有一个 QNetworkAddressEntry 类型的地址列表,通过addressEntries()获得这个列表。
QNetworkAddressEntry 包含了一个网络接口的IP 地址、子网掩码和广播地址,分别用ip(),netmask()和 broadcast()函数返回。
QNetworkInterface::allInterfaces()返回的网络接口的信息很多,如果无需知道子网掩码和广播地址等信息,可以使用QNetworkInterface::allAddresses()只获取IP 地址界面上“QNetworkInterface ::allAddresses()”按钮的响应代码如下:
void HostDialog::on_btnAllAddressed_clicked()
{
QList<QHostAddress> addList = QNetworkInterface::allAddresses();
if(addList.isEmpty())
{
return;
}
for(int i = 0; i < addList.count(); i++)
{
QHostAddress info = addList.at(i);
bool show = ui->chkOnlyIPv4->isChecked();
if(show)
{
show = QAbstractSocket::IPv4Protocol == info.protocol();
}
else
{
show = true;
}
if(show)
{
ui->textInfo->appendPlainText("协议:" + protocolName(info.protocol()));
ui->textInfo->appendPlainText("IP地址:" + info.toString());
ui->textInfo->appendPlainText("");
}
}
}