当前位置: 首页 > news >正文

QT中的网络编程

Qt中的网络编程是通过封装操作系统的API进行实现的

C++标准库中,并没有提供网络编程的封装接口

进行网络编程时本质是在编写应用层代码,需要传输层提供支持

传输层最核心的协议为UDP/TCP

使用Qt网络编程的API时,需要在.pro文件中添加network模块

UDP Socket

Qt中提供进行udp编程的类主要有两个:QUdpSocket和QNetworkDatagram

QUdpSocket表示一个UDP的socket文件

名称

类型

说明

对标原生API

bind(const QHostAddress&,quint16)

方法

绑定指定的端口号

bind

receiveDatagram()

方法

返回

QNetworkDatagram,读取一个UDP数据报

recvfrom

writeDatagram(const QNetworkDatagram&)

方法

发送一个UDP数据报

sendto

readyRead

信号

在收到数据并准备就绪后触发

QNetworkDatagram表示一个UDP数据报

名称

类型

说明

QNetworkDatagram(const QByteArray&,const QHostAddress&,quint16)

构造函数

通过QByteArray,目标IP地址,目标端口号,构造一个UDP数据报,通常用于发送数据时

data()

方法

获取数据报内部持有的数据,返回QByteArray

senderAddress()

方法

获取数据并中包含的对端的IP地址

senderPort()

方法

获取数据报中包含的对端的端口号

例如:

实现基于UDP Socket写一个带有界面的Udp回显服务器

创建一个继承自Widget的文件

在ui界面创建一个list widget用于显示接收到的数据

在.pro文件中加入网络编程模块

在widget头文件中引入<QUdpSocket>头文件,若无法识别则编译一遍再看是否被识别

声明UdpSocket,将其作为成员变量

在构造函数进行实例化,将其挂到对象树,设置服务器窗口标题

在头文件声明处理函数,在构造函数进行信号槽连接

在构造函数绑定端口号

需要先进行信号槽绑定,再绑定端口号,因为绑定端口号后就能接收请求了,若端口号绑定完成后还未绑定信号槽就无法处理请求

在绑定端口号时,还需对返回值判断,避免端口号已经被绑定,导致绑定失败

实现槽函数,读取请求,构建响应,发送响应

在头文件中声明通过读取到的有效数据构建响应中有效数据的函数

实现

构建客户端,实现向服务器发送请求

新建文件继承自Widget,实现客户端

同样在.pro文件加上网络模块

在ui界面创建一个输入框用来接收有效数据,一个pushbutton,用于获取有效数据,构建数据报进行发送,构建一个listwidget用来显示发送的请求

将lineedit和pushbutton放在水平布局中--horizonlayout,再将水平布局放置在垂直布局中,将listwidget放置在垂直布局中

将垂直布局的拉伸系数设为5比1

再将lineedit和pushbutton的sizePolicy中的垂直策略设为expanding

在widget.cpp中定义目的IP,port

在widget.h中引入udpsocket作为成员变量,在构造函数进行定义,修改窗口标题

实现pushbutton的clicked的槽函数,来获取输入框数据,构建数据报进行发送

通过信号槽来处理服务器返回的响应

在widget头文件声明槽函数

在构造函数连接信号槽

实现槽函数

代码编写完成:

先启动服务器,再启动客户端

在客户端发送请求,能够收到响应,进行回显

:ffff是ipV6的环回ip

Qt中udp通信流程:

服务器:

    创建socket,通过connect,连接socket,readyRead信号,和处理对象,处理函数,当收到请求后触发readyRead信号,调用处理函数。再将socket绑定端口号,获取固定端口号收到的数据。

    收到数据后,通过

QNetworkDatagramrequestDatagram=socket->receiveDatagram()

来接收数据报,用

QString request=requestDatagram.data();

提取有效内容,对有效内容---请求进行处理后,构建响应

QNetworkDatagram responseDatagram(response.toUtf8(),requestDatagram.senderAddress(),requestDatagram.senderPort());

将响应通过

 socket->writeDatagram(responseDatagram);

发送给客户端

   客户端:

 创建socket,构建请求数据报,将请求数据报发送到目的服务器

QNetworkDatagram requestDatagram(text.toUtf8(),QHostAddress(SERVER_IP),PORT);

    //发送请求数据并

    socket->writeDatagram(requestDatagram);

接收响应,通过连接socket的readyRead信号,实现槽函数,接收响应读取有效内容

const QNetworkDatagramresponseDatagram=socket->receiveDatagram();

    QString response=responseDatagram.data();

Qt中无法将服务器放写在云服务器上,因为云服务器默认不带图形化界面,Qt程序需要依赖图形化界面来允许

但是可以通过Qt编写的客户端来连接Linux下连接云服务器写的服务器-----常见实现

TCP Socket

核心类是QTcpServer和QTcpSocket

QTcpServer用于监听端口,和获取客户端连接

名称

类型

说明

listen(const QHostAddress& ,quit16port)

方法

绑定指定的地址和端口号,并开始监听

nextPendingConnection()

方法

从系统中获取到一个已经建立好的tcp连接,返回一个QTcpSocket,表示这个客户端的连接,通过这个socket对象完成和客户端之间的通信

newConnection

信号

有新的客户端建立来连接好后触发

QTcpSocket用户客户端和服务器之间的数据交互

名称

类型

说明

readAll()

方法

读取当前接收缓冲区中的所有数据,返回QByteArray()对象

write(const QByteArray&)

方法

把数据写入socket中

deleteLater

方法

暂时把socket对象标记为无效,Qt会在下个事件循环中析构释放该对象

readyRead

信号

有效数据到达并准备就绪时触发

disconnected

信号

连接断开时触发

因为TCP时面向字节流的,所有读取数据和写入数据都是通过QByteArray

QByteArray用来表示一个字节数组,可以与QString进行相互转换

如:

使用QString的构造函数可以把QByteArray转换为QString

使用QString的toUtf8函数即可把QString转换为QByteArray

例如:

实现TCP回显服务器

在.pro文件引入网络模块,在widget头文件引入<QTcpServer>

在ui界面创建listWidget用于显示响应和请求

在构造函数设置窗口标题

在widget.h的类中声明QTcpServer作为成员变量,在构造函数进行初始化,并链入对象树

进行信号槽连接,声明槽函数,实现处理客户端连接

再将tcp设置绑定并监听,来用于获取新连接

实现获取连接后的槽函数,进行获取请求,进行响应,处理客户端断开连接

实现Tcp客户端

新建Widget文件

在.pro文件添加网络模块

在ui界面设计界面添加listwidget,pushbutton,lineEdit,设置布局

在widget.h声明QTcpSocket为成员变量,构造函数处进行初始化

在构造函数进行与服务器的连接

转到按钮的槽函数,实现请求的发送

在构造函数处绑定readyRead信号的槽函数,实现接收服务器的响应

先运行服务器,再启动客户端进行测试

退出客户端后也进行了对应处理

在Linux中多个客户端同时访问一个端口时,就只有一个客户端生效,因为服务端是单线程的,可以引入多线程,每个线程都单独处理一个客户端发送的请求

但是在qt中,上面代码能够处理多个客户端,无需为服务端引入多线程,因为问题的本质原因是在Linux等待客户端连接后,通过死循环来与客户端进行信息传输,若只有一个线程就只能进行一个死循环,而在qt中,无需循环,是通过信号槽来与客户端进行信息传输

HTTP Client

http是应用层协议,http协议的本身是基于Tcp协议实现的,使用一个Http的客户端/服务端,本质上是基于TCP Socket进行封装的

Qt仅提供了HTTP客户端,没有提供HTTP的服务端

主要类为:QNetworkAccessManager,QNetworkRequest,QNetworkReply

QNetworkAccessManager核心操作

方法

说明

get(const QNetworkRequest&)

发起一个HTTP GET请求,返回QNetworkReply对象

post(const QNetworkRequest,const QByteArray&)

发起一个HTTP POST请求,返回QNetworkReply对象

QNetworkRequest表示一个http请求---不包含请求正文

  如果需要发送一个带有body---请求正文的请求,需要使用QNetworkAccessManager的post方法中通过单独的参数传入

方法

说明

QNetworkRequest

通过URL构造一个HTTP请求

setHeader(QNetworkRequest::KnownHeaders header, const QVariant& value)

设置请求头

其中QNetworkRequest::KnownHeaders是一个枚举类型:

取值

说明

ContentTypeHeader

描述body的类型

ContentLengthHeader

描述body的长度

LocationHeader

用于重定向报文中指定的重定向地址(响应中使用)

CookieHeader

设值cookie

UserAgenHeader

设置User-Agent

QNetworkReply表示一个HTTP响应,这个类同时也是QIODevice的子类

方法

说明

error()

获取出错状态

errorString()

获取出错原因的文本

readAll()

读取响应body

header(QNetworkRequest::KnownHeaders header)

读取响应指定header的值

QNetworkReply还提供finished信号,会在客户端收到完整的响应数据之后触发

例:

创建一个继承自Widget的文件

在.pro文件添加网络模块

在ui界面创建一个listWidget用于显示请求和收到的响应内容,一个lineEdit用于输入url,一个按钮用于构建请求并发出

将响应的结果---HTML用QPlainTextEdit---纯文本用来表示,展示原始的html

若使用QTextEdit---富文本则会对htm进行解析渲染---支持标签的使用

将QNetworkAccessManager声明为类成员,在构造函数进行其初始化,和窗口标题定义,输入栏提示

转到pushButton的槽函数进行请求的发送,获取响应

此时就可以进行请求的发送

将plainedit替换为textedit后---支持富文本,并在输出响应时,采用setHtml来写入textedit后:

对标签进行解析

相关文章:

  • [零基础]内网ubuntu映射到云服务器上,http访问(frp内网穿透)
  • FastDDS 解析xml文件
  • neo4j暴露公网ip接口——给大模型联通知识图谱
  • 【uom】 0 配置文件(Cargo.toml)
  • 【DB2】逻辑导出导入注意事项
  • mongoose的介绍,连接数据库
  • 引力透镜效应添加光线弯曲程度可视化层的MATLAB代码
  • Neo4j 的 `SET n += $properties` 语法详解
  • 2025年04月29日Github流行趋势
  • OpenCV 图形API(72)图像与通道拼接函数-----根据指定的方式翻转图像(GMat)函数 flip()
  • zynq上的裸机lwip网络性能测试iperf使用心得
  • UI-TARS论文解读 并提供镜像
  • Elasticsearch:ES|QL lookup JOIN 介绍 - 8.18/9.0
  • 水污染检测数据集VOC+YOLO格式2487张4类别
  • Tshark:强大的命令行网络抓包与分析工具
  • Electron读取本地文件
  • kafka消息的顺序性如何保持一致的
  • Windows 10系统中找回MySQL 8的root密码
  • 智能电子白板的设计与实现:从硬件选型到软件编程
  • python初学
  • 解放日报:上海深化改革开放,系统集成创新局
  • 160名老人报旅行团被扔服务区?张家界官方通报
  • “五一”假期,又有多地将向社会开放政府机关食堂
  • 中国体育报关注徐梦桃、王曼昱、盛李豪等获评全国先进工作者:为建设体育强国再立新功
  • 从咖啡节到话剧、演唱会,上海虹口“文旅商体展”联动促消费
  • A股三大股指收跌:地产股领跌,银行股再度走强