网络简介
在QT中进行网络通信可以使用QT提供的Qt Network模块,该模块提供了用于编写TCP/IP网络应用程序的各种类,如用于TCP通信的QTcpSocket和 QTcpServer,用于 UDP 通信的 QUdpSocket,还有用于网络承载管理的类,以及基于 SSL 协议的用于网络安全通信的类。
要使用该模块,需要在项目配置文件(.pro)中添加如下配置语句:
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(); //只显示IPv4show= 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();//只显示IPv4show= 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(); //只显示IPv4show= 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++开发指南