一.获取主机的网络信息
- 需要添加network模块
cpp
QT += core gui network
- 主要涉及的类分析
QHostInfo类
- QHostInfo::localHostName() 获取本地的主机名
- QHostInfo::fromName(const QString &) 获取指定主机的主机信息 addresses接口
QNetworkInterface类
- QNetworkInterface::allAddresses() 网卡所有的IP地址
- 项目效果
- 源码如下
cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QHostInfo>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
//获取主机名
void GetHostName();
//获取IPV4
void GetIPV4();
//获取IPV6
void GetIPV6();
//清除文本内容
void Clear_Text();
//获取指定域名的IP地址
void Get_DefineHost();
void lookedUp(QHostInfo hostInfo);
//主机所有网卡IP地址
void GetAlladdresses();
//所有网卡的网络信息
void GetNetWorkInfo();
private:
void InitConnectSignals();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QHostInfo>
#include<QNetworkInterface>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("主机的网络信息");
InitConnectSignals();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::GetHostName()
{
//获取当前的主机名
QString hostname = QHostInfo::localHostName();
ui->textEdit->append("当前的主机名为:"+hostname);
}
void MainWindow::GetIPV4()
{
//获取当前的主机名
QString hostname = QHostInfo::localHostName();
//获取指定主机的主机信息
QHostInfo hostinformation = QHostInfo::fromName(hostname);
//Returns the list of IP addresses associated with hostName().
//This list may be empty.
//返回与hostName()相关联的IP地址列表。
//该列表可能为空。
QList<QHostAddress> addrlist = hostinformation.addresses();
ui->textEdit->append("本机的IPV4地址如下:");
if(!addrlist.isEmpty())
{
//for遍历输出
for(int i=0;i<addrlist.size();i++)
{
//protocol是协议的意思
if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
{
ui->textEdit->append(addrlist[i].toString());
}
}
}
}
void MainWindow::GetIPV6()
{
//获取当前的主机名
QString hostname = QHostInfo::localHostName();
//获取指定主机的主机信息
QHostInfo hostinformation = QHostInfo::fromName(hostname);
//Returns the list of IP addresses associated with hostName().
//This list may be empty.
//返回与hostName()相关联的IP地址列表。
//该列表可能为空。
QList<QHostAddress> addrlist = hostinformation.addresses();
ui->textEdit->append("本机的IPV6地址如下:");
if(!addrlist.isEmpty())
{
//for遍历输出
for(int i=0;i<addrlist.size();i++)
{
//protocol是协议的意思
if(addrlist[i].protocol()==QAbstractSocket::IPv6Protocol)
{
ui->textEdit->append(addrlist[i].toString());
}
}
}
}
void MainWindow::Clear_Text()
{
ui->textEdit->clear();
}
void MainWindow::Get_DefineHost()
{
//获取lineEdit上的域名
QString hostName =ui->lineEdit->text();
if(hostName.isEmpty())
{
return ;
}
//获取域名的IPV4信息
/*
查找与主机名name相关联的IP地址,并返回用于查找的ID。当查找结果准备好时,
将使用QHostInfo参数调用receiver中的slot或信号成员。然后可以检查QHostInfo对象以获得查找结果。
*/
//lookupHost(const QString &name, QObject *context, Func1 slot)
QHostInfo::lookupHost(hostName,this,SLOT(lookedUp(QHostInfo)));
}
void MainWindow::lookedUp(QHostInfo hostInfo)
{
//当前的主机名
QString hostName=hostInfo.hostName();
ui->textEdit->append("当前域名为:"+hostName+" IPV4信息如下:");
QList<QHostAddress> addrlist = hostInfo.addresses();
if(!addrlist.isEmpty())
{
for(int i=0;i<addrlist.count();i++)
{
if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
{
ui->textEdit->append(addrlist[i].toString());
}
}
}
/*
常见的错误
QObject::connect: Incompatible sender/receiver arguments
QHostInfoResult::resultsReady(QHostInfo) --> MainWindow::lookedUp(QHostInfo&)
信号和槽的参数不匹配
*/
}
void MainWindow::GetAlladdresses()
{
//获取网卡的所有IP信息
ui->textEdit->append("所有网卡的IPV4信息如下:");
QList<QHostAddress>addrlist = QNetworkInterface::allAddresses();
if(!addrlist.isEmpty())
{
for(int i=0;i<addrlist.count();i++)
{
if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol)
{
ui->textEdit->append(addrlist[i].toString());
}
}
}
}
void MainWindow::GetNetWorkInfo()
{
//获取所有网卡的网络信息
QList<QNetworkInterface>list =QNetworkInterface::allInterfaces();
for(int i=0;i<list.count();i++)
{
QNetworkInterface interface = list[i];
if(!interface.isValid())
{
continue;
}
ui->textEdit->append("设备名称:"+interface.humanReadableName());
ui->textEdit->append("硬件地址:"+interface.hardwareAddress());
//一个网卡,可以有多个IP地址
QList<QNetworkAddressEntry> list2 = interface.addressEntries();
for(int j=0; j<list2.count(); j++)
{
QNetworkAddressEntry entry = list2[j];
ui->textEdit->append("\tIP地址:" + entry.ip().toString());
ui->textEdit->append("\t子网掩码:" + entry.netmask().toString());
ui->textEdit->append("\t广播地址: " + entry.broadcast().toString() + "\n");
}
}
}
void MainWindow::InitConnectSignals()
{
//void pressed();
connect(ui->pushButton_HostName,SIGNAL(pressed()),this,SLOT(GetHostName()));
connect(ui->pushButton_IPV4,SIGNAL(pressed()),this,SLOT(GetIPV4()));
connect(ui->pushButton_IPV6,SIGNAL(pressed()),this,SLOT(GetIPV6()));
connect(ui->pushButton_Clear,SIGNAL(pressed()),this,SLOT(Clear_Text()));
connect(ui->pushButton_DefineHost,SIGNAL(pressed()),this,SLOT(Get_DefineHost()));
connect(ui->pushButton_Alladdresses,SIGNAL(pressed()),this,SLOT(GetAlladdresses()));
connect(ui->pushButton_Network,SIGNAL(pressed()),this,SLOT(GetNetWorkInfo()));
}
二.TCP编程
1. server编程(服务器端实现)
-
项目效果
-
客户端(使用的是调试助手)
-
项目源码
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QLabel>
#include<QHostInfo>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
InitUI();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::InitUI()
{
//加状态栏中添加控件
label_first=new QLabel();
label_second=new QLabel();
label_third=new QLabel();
label_four=new QLabel();
label_first->setText("监听状态:");
label_third->setText("套接字状态:");
label_first->setMaximumWidth(80);
label_third->setMaximumWidth(80);
label_second->setMinimumWidth(100);
label_four->setMinimumWidth(100);
ui->statusbar->addWidget(label_first);
ui->statusbar->addWidget(label_second);
ui->statusbar->addWidget(label_third);
ui->statusbar->addWidget(label_four);
//fromName 返回指定主机的主机信息
QHostInfo hostInfo = QHostInfo::fromName(QHostInfo::localHostName());
QList<QHostAddress> addrlist = hostInfo.addresses();
if(!addrlist.isEmpty())
{
for(int i=0;i<addrlist.count();i++)
{
QHostAddress address = addrlist[i];
if(address.protocol()==QAbstractSocket::IPv4Protocol)
{
ui->comboBox->addItem(address.toString());
}
}
}
//本机的环回网卡的IP 127.0.0.1
//用来做网络测试的
ui->comboBox->addItem("127.0.0.1");
//处理tcp通信
tcpserver=new QTcpServer(this);
//发现新信号就触发onNewConnection
connect(tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}
void MainWindow::on_actionListen_triggered()
{
QString ip =ui->comboBox->currentText();
//unsigned short
quint16 port = ui->spinBox->value();
QHostAddress addr(ip);
//开始监听
tcpserver->listen(addr,port);
label_second->setText("已开始监听");
ui->textEdit->append("开始监听,等待客户端发起连接...");
ui->textEdit->append("服务器地址:"+tcpserver->serverAddress().toString());
ui->textEdit->append("服务器端口:"+QString::number(tcpserver->serverPort()));
//更改控件
ui->actionStop->setEnabled(true);
ui->actionListen->setEnabled(false);
}
void MainWindow::on_actionStop_triggered()
{
//停止监听
if(tcpserver->isListening())
{
tcpserver->close();
ui->actionListen->setEnabled(true);
ui->actionStop->setEnabled(false);
label_second->setText("已停止监听");
}
}
void MainWindow::on_actionClear_triggered()
{
label_second->clear();
label_four->clear();
ui->textEdit->clear();
}
void MainWindow::onNewConnection()
{
//一旦有新的连接
//难以理解的概念:套接字,相当于客户端套接字,每当有客户端发起请求,服务器就会分配一个套接字
//去接待
tcpsocket=tcpserver->nextPendingConnection();//取出要服务,相当于是分配一个服务人员
//连接成功会触发的
connect(tcpsocket,SIGNAL(connected()),this,SLOT(onConnected()));
//当有数据可以读的时候,我们就读数据,(使用信号槽)
connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
connect(tcpsocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
// void stateChanged(QAbstractSocket::SocketState);
connect(tcpsocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
onSocketStateChanged(tcpsocket->state());//先更新一下状态
}
void MainWindow::onSocketReadyRead()
{
//有数据可读时
while(tcpsocket->canReadLine())
{
ui->textEdit->append("[收到]"+tcpsocket->readLine());
}
}
void MainWindow::onConnected()
{
//刚连入成功
ui->textEdit->append("\n客户端请求已经接入!");
//获取客户端的地址信息
ui->textEdit->append("客户端地址:"+tcpsocket->peerAddress().toString());
ui->textEdit->append("客户端端口号:"+QString::number(tcpsocket->peerPort()));
}
void MainWindow::onDisconnected()
{
ui->textEdit->append("\n客户端已断开连接");
tcpsocket->deleteLater();//以后在删除,这样更安全
}
void MainWindow::onSocketStateChanged(QAbstractSocket::SocketState status)
{
/*
UnconnectedState,
HostLookupState,
ConnectingState,
ConnectedState,
BoundState,
ListeningState,
ClosingState
*/
//套接字状态发生变化
switch(status)
{
case QAbstractSocket::UnconnectedState:
label_four->setText("未连接");
break;
case QAbstractSocket::HostLookupState:
label_four->setText("正在查找主机名");
break;
case QAbstractSocket::ConnectingState:
label_four->setText("正在连接");
break;
case QAbstractSocket::ConnectedState:
label_four->setText("已连接");
break;
case QAbstractSocket::BoundState:
label_four->setText("已绑定到IP地址和端口号");
break;
case QAbstractSocket::ListeningState:
label_four->setText("正在监听");
break;
case QAbstractSocket::ClosingState:
label_four->setText("准备关闭");
break;
}
}
void MainWindow::on_pushButton_clicked()
{
//发送一行字符串
QString msg = ui->lineEdit->text();
//utf编码,QByteArray在功能上很像字符数组
QByteArray str=msg.toUtf8();
str.append('\n');
//服务器向客户端发送数据
tcpsocket->write(str);
}
void MainWindow::on_actionQuit_triggered()
{
close();
}
2. 客户端实现
-
效果展示
-
源码如下
cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建了客户端的套接字对象
tcpsocket=new QTcpSocket(this);
//连接成功会触发的
connect(tcpsocket,SIGNAL(connected()),this,SLOT(onConnected()));
//当有数据可以读的时候,我们就读数据,(使用信号槽)
connect(tcpsocket,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
connect(tcpsocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
// void stateChanged(QAbstractSocket::SocketState);
connect(tcpsocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChanged(QAbstractSocket::SocketState)));
ui->actionConnect->setEnabled(true);
ui->actionDisconnect->setEnabled(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onConnected()
{
//peerAddress对等地址
//打印服务器的地址
ui->plainTextEdit->appendPlainText("已连接到服务器!");
ui->plainTextEdit->appendPlainText("---服务器地址:"+
tcpsocket->peerAddress().toString());
ui->plainTextEdit->appendPlainText("---服务器端口:"+
QString::number(tcpsocket->peerPort()));
}
void MainWindow::onDisconnected()
{
ui->plainTextEdit->appendPlainText("服务器的连接已经断开");
ui->actionConnect->setEnabled(true);
ui->actionDisconnect->setEnabled(false);
}
void MainWindow::onSocketStateChanged(QAbstractSocket::SocketState status)
{
//这和服务器端的判断一样的
}
void MainWindow::onSocketReadyRead()
{
while(tcpsocket->canReadLine())
{
ui->plainTextEdit->appendPlainText("[收到]"+tcpsocket->readLine());
}
}
void MainWindow::on_actionConnect_triggered()
{
QString ip = ui->lineEditIP->text();
quint16 port=ui->spinBoxPort->value();
tcpsocket->connectToHost(ip,port);
}
void MainWindow::on_actionDisconnect_triggered()
{
if(tcpsocket->state()==QAbstractSocket::ConnectedState)
{
//从主机那断开
tcpsocket->disconnectFromHost();
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(tcpsocket->state()==QAbstractSocket::ConnectedState)
{
//从主机那断开
tcpsocket->disconnectFromHost();
}
event->accept();//不调用这个窗口就不会关闭
//event->ignore();这个窗口就不关闭
}
void MainWindow::on_actionClear_triggered()
{
ui->plainTextEdit->clear();
}
void MainWindow::on_actionQuit_triggered()
{
close();
}
void MainWindow::on_pushButton_clicked()
{
QString msg = ui->lineEditSend->text();
QByteArray str=msg.toUtf8();
str.append('\n');
tcpsocket->write(str);
ui->plainTextEdit->appendPlainText("[发送]"+msg);
ui->lineEditSend->clear();
ui->lineEditSend->setFocus();//设置光标聚焦
}