Qt 网络编程实战
一.获取主机的网络信息
- 需要添加network模块
QT += core gui network
- 主要涉及的类分析
QHostInfo类
- QHostInfo::localHostName() 获取本地的主机名
- QHostInfo::fromName(const QString &) 获取指定主机的主机信息 addresses接口
QNetworkInterface类
- QNetworkInterface::allAddresses() 网卡所有的IP地址
- 项目效果
- 源码如下
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include 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
#include "mainwindow.h" #include "ui_mainwindow.h" #include #include 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 addrlist = hostinformation.addresses(); ui->textEdit->append("本机的IPV4地址如下:"); if(!addrlist.isEmpty()) { //for遍历输出 for(int i=0;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 addrlist = hostinformation.addresses(); ui->textEdit->append("本机的IPV6地址如下:"); if(!addrlist.isEmpty()) { //for遍历输出 for(int i=0;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 addrlist = hostInfo.addresses(); if(!addrlist.isEmpty()) { for(int i=0;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信息如下:"); QListaddrlist = QNetworkInterface::allAddresses(); if(!addrlist.isEmpty()) { for(int i=0;i if(addrlist[i].protocol()==QAbstractSocket::IPv4Protocol) { ui-textEdit->append(addrlist[i].toString()); } } } } void MainWindow::GetNetWorkInfo() { //获取所有网卡的网络信息 QListlist =QNetworkInterface::allInterfaces(); for(int i=0;i QNetworkInterface interface = list[i]; if(!interface.isValid()) { continue; } ui-textEdit->append("设备名称:"+interface.humanReadableName()); ui->textEdit->append("硬件地址:"+interface.hardwareAddress()); //一个网卡,可以有多个IP地址 QList list2 = interface.addressEntries(); for(int j=0; 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编程(服务器端实现)
-
项目效果
-
客户端(使用的是调试助手)
-
项目源码
#include "mainwindow.h" #include "ui_mainwindow.h" #include #include 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 addrlist = hostInfo.addresses(); if(!addrlist.isEmpty()) { for(int i=0;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. 客户端实现
-
效果展示
-
源码如下
#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();//设置光标聚焦 }
-
- QNetworkInterface::allAddresses() 网卡所有的IP地址
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。