网络简介
在QT中进行网络通信可以使用QT提供的Qt Network模块,该模块提供了用于编写TCP/IP网络应用程序的各种类,如用于TCP通信的QTcpSocket和 QTcpServer,用于 UDP 通信的 QUdpSocket,还有用于网络承载管理的类,以及基于 SSL 协议的用于网络安全通信的类。
要使用该模块,需要在项目配置文件(.pro)中添加如下配置语句:
QT += network
使用 QHostInfo 类和 QNetworkInterface 类可以获取主机的一些网络信息,如 IP 地址和 MAC 地址,这是网络通信应用需要获取的基本信息。
QHostInfo 类
可以根据主机名获取主机的 IP 地址,或者通过 IP 地址获取主机名。
该类的主要接口函数如下表:
QHostInfo 类的静态函数 localHostName()可获取本机的主机名,静态函数 fromName()可以通过主机名获取 IP地址,静态函数 lookupHost()可以通过一个主机名以异步方式查找这个主机的 IP 地址。
QNetworkInterfac 类
可以获得运行程序的主机的所有 IP 地址和网络接口列表。
该类的主要接口函数如下表:
静态函数 allInterfaces()返回主机上所有的网络接口列表,一个网络接口可能包含多个 IP 地址,每个 IP 地址与掩码或广播地址关联。如果无须知道子网掩码和广播地址,使用静态函数allAddresses()可以获得主机上所有 IP 地址的列表。
示例程序解读
显示本机地址信息
使用QHostInfo 类
void MainWindow::on_btnGetHostInfo_clicked()
{//"获取本机主机名和IP地址" 按钮
ui->textEdit->clear();
QString hostName=QHostInfo::localHostName(); //本地主机名
ui->textEdit->appendPlainText("本机主机名:"+hostName+"\n");
QHostInfo hostInfo=QHostInfo::fromName(hostName); //本机IP地址
QList<QHostAddress> addrList=hostInfo.addresses(); //IP地址列表
if (addrList.isEmpty())
return;
foreach (QHostAddress host, addrList)
{
bool show=ui->chkBox_OnlyIPv4->isChecked(); //只显示IPv4
show= show? (host.protocol()==QAbstractSocket::IPv4Protocol):true;
if (show)
{
ui->textEdit->appendPlainText("协 议:"+protocolName(host.protocol())); //协议类型
ui->textEdit->appendPlainText("本机IP地址:"+host.toString()); //IP地址
ui->textEdit->appendPlainText(QString("isGlobal()=%1\n").arg(host.isGlobal()));
// ui->textEdit->appendPlainText(QString("isBroadcast()=%1").arg(host.isBroadcast()));
// ui->textEdit->appendPlainText(QString("isLoopback()=%1").arg(host.isLoopback()));
// ui->textEdit->appendPlainText(QString("isMulticast()=%1\n").arg(host.isMulticast()));
}
}
}
QString MainWindow::protocolName(QAbstractSocket::NetworkLayerProtocol protocol)
{//通过协议类型返回协议名称
switch(protocol)
{
case QAbstractSocket::IPv4Protocol:
return "IPv4";
case QAbstractSocket::IPv6Protocol:
return "IPv6";
case QAbstractSocket::AnyIPProtocol:
return "Any Internet Protocol";
default:
return "Unknown Network Layer Protocol";
}
}
1、通过静态函数QHostInfo::localHostName()获取本机主机名 hostName,然后使用静态函数 QHostInfo::fromName(hostName)获取主机的信息 hostInfo。
2、通过hostInfo.addresses()可以获取到主机的ip地址列表,有无线局域网WLAN、以太网,如果安装了虚拟机配置了相关地址,还会出现一些名如VMnetx的网络地址(NAT或桥接)。
在cmd中运行ipconfig命令得到的结果如下所示:
3、addrList 是 QHostAddress 类型的列表,提供 IP 地址的信息,包括 IPv4 地址和 IPv6 地址,可以通过QHostAddress::protocol()函数来获取IP地址的类型。
使用QNetworkInterface 类
该类也可以实现应用程序所在主机的所有网络接口的信息,包括子网掩码和广播地址。可以使用静态函数 QNetworkInterface::allAddresses()获取 IP 地址:
void MainWindow::on_btnAllAddress_clicked()
{//"allAddresses()"按钮
ui->textEdit->clear();
QList<QHostAddress> addrList=QNetworkInterface::allAddresses();
if (addrList.isEmpty())
return;
foreach (QHostAddress host, addrList)
{
bool show=ui->chkBox_OnlyIPv4->isChecked();//只显示IPv4
show= show? (host.protocol()==QAbstractSocket::IPv4Protocol):true;
if (show)
{
ui->textEdit->appendPlainText("协 议:"+protocolName(host.protocol()));
ui->textEdit->appendPlainText("IP地址:"+host.toString());
ui->textEdit->appendPlainText(QString("isGlobal()=%1\n").arg(host.isGlobal()));
}
}
}
QNetworkInterface::allAddresses()的功能与 QHostInfo::addresses()的功能相似,都是返回一个
QHostAddress 类型的列表。区别是:QNetworkInterface 会返回更多地址,包括表示本机的 IP 地址127.0.0.1,而 QHostInfo 不会返回这个 IP 地址。
如果想要获取更多的信息,如子网掩码和广播地址等信息等,可以使用静态函数 allInterfaces()获取所有网络接口的列表:
void MainWindow::on_btnAllInterface_clicked()
{//"allInterfaces()"按钮
ui->textEdit->clear();
QList<QNetworkInterface> list=QNetworkInterface::allInterfaces(); //网络接口列表
foreach(QNetworkInterface interface,list)
{
if (!interface.isValid())
continue;
ui->textEdit->appendPlainText("设备名称:"+interface.humanReadableName());
ui->textEdit->appendPlainText("硬件地址:"+interface.hardwareAddress());
ui->textEdit->appendPlainText("接口类型:"+interfaceType(interface.type()));
QList<QNetworkAddressEntry> entryList=interface.addressEntries(); //地址列表
foreach(QNetworkAddressEntry entry, entryList)
{
ui->textEdit->appendPlainText(" IP 地址:"+entry.ip().toString());
ui->textEdit->appendPlainText(" 子网掩码:"+entry.netmask().toString());
ui->textEdit->appendPlainText(" 广播地址:"+entry.broadcast().toString()+"\n");
}
}
}
QString MainWindow::interfaceType(QNetworkInterface::InterfaceType type)
{//根据枚举值返回字符串
switch(type)
{
case QNetworkInterface::Unknown:
return "Unknown";
case QNetworkInterface::Loopback:
return "Loopback";
case QNetworkInterface::Ethernet:
return "Ethernet";
case QNetworkInterface::Wifi:
return "Wifi";
default:
return "Other type";
}
}
每个接口包含设备名称、硬件地 址和接口类型。每个接口有一个 QNetworkAddressEntry 类型的地址列表,通过函数 addressEntries()可获得这个列表。QNetworkAddressEntry 类包含网络接口的 IP 地址、子网掩码和广播地址,可分别用 ip()、netmask()和 broadcast()函数获取。
该示例显示的内容与在cmd使用ipconfig得到的结果大致相同。
查找主机地址信息
QHostInfo 的静态函数 lookupHost()可以根据主机名查找主机的地址信息。原型如下:
int QHostInfo::lookupHost(const QString &name, QObject *receiver, const char *member)
参数 name 是表示主机名的字符串,可以是主机名、域名或 IP 地址。参数 receiver 和 member 指定接收者和槽函数名称。
注意:该函数以异步方式查找主机地址,运行 lookupHost()函数后,程序可能需要花一定时间来查找主机地址,但运行该函数不会阻塞程序的运行。当查找到主机地址后,通过发射信号通知设定的槽函数,在槽函数里读取查找的结果。
void MainWindow::on_btnLookup_clicked()
{//"查找域名的IP地址" 按钮
ui->textEdit->clear();
QString hostname=ui->comboBox->currentText(); //读取主机名
ui->textEdit->appendPlainText("正在查找查找主机信息:"+hostname);
QHostInfo::lookupHost(hostname,this,SLOT(do_lookedUpHostInfo(QHostInfo)));
}
void MainWindow::do_lookedUpHostInfo(const QHostInfo &host)
{//查找主机信息的槽函数
QList<QHostAddress> addrList=host.addresses(); //获取主机的地址列表
if (addrList.isEmpty())
return;
foreach(QHostAddress host, addrList)
{
bool show=ui->chkBox_OnlyIPv4->isChecked(); //只显示IPv4
show= show? (host.protocol()==QAbstractSocket::IPv4Protocol):true;
if (show)
{
ui->textEdit->appendPlainText("协 议:"+protocolName(host.protocol()));
ui->textEdit->appendPlainText(host.toString());
ui->textEdit->appendPlainText(QString("isGlobal()=%1\n").arg(host.isGlobal()));
}
}
}
如上代码中,当通过lookupHost()查询到主机后,会将查询到的QHostInfo类型变量通过信号传递到槽函数中,和上一步骤一样,通过addresses()获取到IP地址列表后打印输出。
参考
QT6 C++开发指南