Qt 网络编程实战

一.获取主机的网络信息

  1. 需要添加network模块
QT   += core gui network
  1. 主要涉及的类分析

QHostInfo类

  • QHostInfo::localHostName() 获取本地的主机名
  • QHostInfo::fromName(const QString &) 获取指定主机的主机信息 addresses接口

QNetworkInterface类

  • QNetworkInterface::allAddresses() 网卡所有的IP地址
  1. 项目效果

在这里插入图片描述

  1. 源码如下
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include<QHostInfo>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots://获取主机名void GetHostName();//获取IPV4void GetIPV4();//获取IPV6void 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<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 argumentsQHostInfoResult::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编程(服务器端实现)

  • 项目效果
    在这里插入图片描述

  • 客户端(使用的是调试助手)
    在这里插入图片描述

  • 项目源码

#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);//发现新信号就触发onNewConnectionconnect(tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));}void MainWindow::on_actionListen_triggered()
{QString ip =ui->comboBox->currentText();//unsigned shortquint16 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();//设置光标聚焦
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1475086.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

AI绘画Stable Diffusion:超强InstantID插件—面部特征一致性风格保持与迁移,轻松搞定私人写真摄影,SDWebUI使用指南

大家好&#xff0c;我是设计师阿威 最近经常有同学问到AI绘画Stable Diffusion 关于风格迁移IPA、Instant ID等安装和使用方法&#xff0c;内容虽基础但也属常用工具。因此&#xff0c;本文将核心介绍Instant ID 使用和墨幽人造人XL体验&#xff08;这是一款可出图商用的写实摄…

uniapp微信小程序端实现微信登录

从网上看了一些&#xff0c;好像说是要先调用uni.getUserProfile 或者uni.getUserInfo获取用户信息后&#xff0c;然后再调用uni.login才行&#xff0c;但是我看着uni.getUserProfile和uni.getUserInfo 返回的都是一些匿名信息&#xff08;nickName: "微信用户", 头像…

经济寒冬:竞品凶猛,你的产品如何求生?

那些年曾被竞品干掉的产品 1997年到2010年左右是国内互联网行业的快速发展和多元化发展的时期&#xff0c;这一时期涌现出来一大批优秀的产品&#xff0c;市场竞争越来越激烈。苹果 在20 世纪 80 年代&#xff0c;乔布斯的苹果电脑&#xff0c;在当时可是PC行业的老大&#xf…

tessy 单元测试:小白入门指导手册

目录 1,创建单元测试工程目录 2,导入单元测试源文件 一:创建测试文件夹(最好和代码目录一一对应,方便查找) 二:选择测试环境 三:添加源文件 四:分析源文件 3,编写单元测试用例 一:设置函数参数的传输方向 二:添加单元测试用例 三:编辑单元测试用例数据 …

Kafka抛弃Zookeeper后如何启动?

Kafaka如何下载 官网地址 目前Kafka最新的版本就是3.7.1 我们可以看到下面这两个版本信息&#xff1f;什么意思呢&#xff1f; Scala 2.12 - kafka_2.12-3.7.1.tgz (asc, sha512)Scala 2.13 - kafka_2.13-3.7.1.tgz (asc, sha512) 我们应该知道&#xff0c;一个完整的Kafka实…

互联网十万个为什么之什么是数据备份?

数据备份是按照一定的备份频率创建数据副本的过程&#xff0c;将重要的数据复制到其它位置或者存储介质&#xff0c;并对生成的副本保留一定的时长。备份通常储存在不同的物理介质或云端&#xff0c;以确保数据的连续性和完整性。有效的备份策略至关重要&#xff0c;以防止数据…

c#类型转换和常见集合类型

目录 1. 整数转换&#xff0c;整数和字符串&#xff0c;字符串和整数之间的转换怎么实现&#xff1f; 2. 日期转换&#xff0c;获取当前日期&#xff0c;字符串转日期&#xff0c;日期转字符串怎么实现&#xff1f; 3. 举例一维、二维、三维数组 4. 需求&#xff1a;有个88…

07浅谈大语言模型可调节参数tempreture

浅谈temperature 什么是temperature&#xff1f; temperature是大预言模型生成文本时常用的两个重要参数。它的作用体现在控制模型输出的确定性和多样性&#xff1a; 控制确定性&#xff1a; temperature参数可以控制模型生成文本的确定性&#xff0c;大部分模型中temperatur…

《C++20设计模式》命令模式思考

文章目录 一、前言二、分析 拆解1、经典命令模式2、撤销操作3、关于Invoker类 三、实现 一、前言 哎&#xff01;只要是书上写的和经典设计模式不同&#xff0c;我就会很伤脑筋。&#x1f629; 命令模式到底是干什么的&#xff1f; 答&#xff1a;命令的发送者和接收者完全解…

SQLServer的系统数据库用别的服务器上的系统数据库替换后做跨服务器连接时出现凭证、非对称金钥或私密金钥的资料无效

出错作业背景&#xff1a; 公司的某个sqlserver服务器要做迁移&#xff0c;由于该sqlserver服务器上数据库很多&#xff0c;并且做了很多的job和维护计划&#xff0c;重新安装的sqlserver这些都是空的&#xff0c;于是就想到了把系统4个系统数据库进行替换&#xff0c;然后也把…

应用在灯带Type-C接口上的PD SINK协议芯片ECP5701/ECP5702获取充电器的5V、9V、12V、15V、20V供电

方案背景 近日&#xff0c;欧盟就统一充电器接口的提案达成了一项政治协议&#xff0c;其中规定了在欧盟地区销售的所有手机或其他便携式中小型电子设备必须采用统一的USB Type-C接口。这项决定意味着未来将会有更多的产品强制性地使用TYPE-C充电接口。 在这个背景下&#xf…

算法设计与分析 实验5 并查集法求图论桥问题

目录 一、实验目的 二、问题描述 三、实验要求 四、实验内容 &#xff08;一&#xff09;基准算法 &#xff08;二&#xff09;高效算法 五、实验结论 一、实验目的 1. 掌握图的连通性。 2. 掌握并查集的基本原理和应用。 二、问题描述 在图论中&#xff0c;一条边被称…

剑指西门子ABB施耐德,中国自动化公司杀入全球市场,业绩增长90%

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 更多的海量【智能制造】相关资料&#xff0c;请到智能制造online知识星球自行下载。 一提到工业自动化领域&#xff0c;西门子、施耐德、ABB这些…

vue-使用Worker实现多标签页共享一个WebSocket

文章目录 前言一、SharedWorker 是什么SharedWorker 是什么SharedWorker 的使用方式SharedWorker 标识与独占 二、Demo使用三、使用SharedWorker实现WebSocket共享 前言 最近有一个需求&#xff0c;需要实现用户系统消息时时提醒功能。第一时间就是想用WebSocket进行长连接。但…

植物神经紊乱小救星来啦!放松小技巧get√

哈喽&#xff0c;小伙伴们&#xff01;今天给大家带来一些超级实用的放松小技巧&#xff0c;特别适合那些时常感到植物神经紊乱&#xff0c;心情紧绷的亲人们哦&#xff01;&#x1f478; &#x1f340;首先&#xff0c;深呼吸大法&#xff01;每次感到紧张或者焦虑的时候&…

小试牛刀-Python生成solana Wallet公私钥

目录 1.编写目的 2.使用依赖 3.实现方法 3.1 Pynacl实现 3.2 ed25519实现 1.编写目的 在使用Python开发solana应用过程中,需要生成solana Wallet公私钥,以实现后续应用操作.这里将Python生成方法进行整理,方便日后的查阅,也能帮助到实现相关功能的朋友。 2.使用依赖 主要…

(十四)向量和矩阵

向量 标量&#xff1a;比如质量/温度/颜色等&#xff0c;没有方向&#xff0c;只有大小的量&#xff0c;称为标量 向量&#xff1a;拥有方向跟大小的物理量/数学量为向量&#xff0c;比如力/速度 向量特性&#xff1a; 1.向量有方向&#xff0c;没有位置 2.向量有大小&#x…

Linux的前世今生

Unix的起源和发展 1969年&#xff0c;AT&T贝尔实验室的Ken Thompson和Dennis Ritchie等人开发了Unix操作系统。Unix的设计理念强调小而简洁的工具&#xff0c;文本流和系统模块化&#xff0c;这些理念后来成为Linux开发的重要基础。1973年&#xff0c;Unix用C语言重新编写…

Angular进阶之九: JS code coverage是如何运作的

环境准备 需要用到的包 node 18.16.0# Javascript 代码编辑"babel/core": "^7.24.7","babel/preset-env": "^7.24.7","babel-loader": "^9.1.3",# 打包时使用的 module&#xff0c; 给代码中注入新的方法# http…

MySQL如何实现数据排序

根据explain的执行计划来看&#xff0c;MySQL可以分为索引排序和filesort 索引排序 如果查询中的order by字句包含的字段已经在索引中&#xff0c;且索引的排列顺序和order by子句一致&#xff0c;则可直接利用索引进行排序&#xff0c;由于索引有序&#xff0c;所以排序效率…