Qt:网络编程
目录
UDP Socket
UDP服务器编写
UDP客户端编写
TCP Socket
TCP服务器编写
TCP客户端编写
HTTP Client
网络编程,操作系统提供的一组 API(Socket API)
C++ 标准库中,并没有提供网络编程的 api 的封装
进行网络编程的时候,本质上是在编写应用层代码,需要传输层提供支持
传输层最核心的协议,有 UDP 和 TCP,并且这俩协议差别还很大,Qt 也就提供了两套 API
注意:
使用 Qt 网络编程的 APl,需要先在 .pro 文件中添加 network 模块
之前学过的 Qt 的各种控件,各种内容,都是包含在 QtCore 模块中的(是默认就添加的)
Qt 是模块化处理的:
其他的功能分别封装成不同的模块
默认情况下这些额外的模块不会参与编译
需要在 .pro 文件中引入对应的模块,才能把对应功能给编译加载进来
UDP Socket
UDP Socket 主要的类有两个,QUdpSocket 和 QNetworkDatagram
QUdpSocket 表示一个UDP 的 socket 文件
QNetworkDatagram 表示一个 UDP 数据报
写一个带有界面的 UDP 回显服务器
UDP服务器编写
图形化界面的方式拖动一个 List Widget:
List Widget表示若干条消息,每一个消息都是里面的 item
在 .pro 文件中加入 newwork,这样才能引入网络相关的操作:
在 widget.h 中新增一个 socket 成员和 processRequest 槽函数用于处理请求:
构造函数为:
下面实现 processRequest 函数:
UDP客户端编写
UDP客户端编写时,同样需要在对应的 .pro 文件中添加 network
此时写的客户端,要能够主动给服务器发起请求
所以下面创建的 ui 界面下方是一个输入框 + 发送按钮,上面是 List Widget,显示服务器返回的内容(也可以显示已经发送的内容):
通过改动垂直和水平策略:
并通过 ui 界面上方的布局管理器设置如下:
在 widget.h 中创建 socket 对象:
在 widget.cpp 中定义两个常量,并编写构造函数:
因为点击发送按钮需要完成相关行为,所以编写发送按钮的槽函数:
实现 processResponse 槽函数,处理客户端收到服务器发的信号:
客户端服务器程序测试时候的基本的原则,一定是先启动服务器,后启动客户端
首先在客户端中输入 hello,点击发送:
服务器显示:
客户端显示:
如果创建多个客户端也能够完成上述要求:
TCP Socket
核心类是两个:QTcpServer和QTcpSocket
QTcpServer用于监听端口,和获取客户端连接
QTcpSocket 用户客户端和服务器之间的数据交互
TCP服务器编写
第一步就是在 .pro 文件的第一行加入 network
页面和UDP的页面一样,都是一个 List Widget:
widget.h 中新增一个成员,一个函数:
widget.cpp 中的构造函数如下:
实现 processConnection 函数:
- peerAddress() 表示对端的地址
- peerPort() 表示对端的端口
- 之前学 Linux 网络编程,需要搞一个循环,循环的读取请求循环的处理
在 Qt 中基于信号槽就不必循环了
每次客户端发来请求,都能触发 readyRead 信号,即使有多个请求,槽函数也是可以顺利的执行到的 - deleteLater这个操作,不是立即销毁 clientSocket,而是告诉 Qt,下一轮事件循环中,再进行上述的销毁操作
process 函数:
TCP客户端编写
与UDP客户端界面是一样的
widget.h 新增成员 socket:
widget.cpp 的构造函数如下:
此处这个 connectToHost 函数不会阻塞等待三次握手完毕(非阻塞的函数)
原生的 Linux api, 也有一个 connect 函数,一般来说一个 socket 默认都是阻塞IO通信的,此时针对这样的socket 进行 connect 也就是阻塞的了
发送按钮的槽函数实现:
此时运行程序,客户端输入内容,会有客户端输入的和服务器回显的:
服务器也会显示客户端上线,客户端发送的内容:
如果客户端关闭,服务器也会收到客户端下线的提示:
HTTP Client
进行 Qt 开发时,和服务器之间的通信很多时候也会用到 HTTP 协议
HTTP 使用比 TCP /UDP 更多一些
- 通过 HTTP 从服务器获取数据
- 通过 HTTP 向服务器提交数据
Qt 中也提供了 HTTP 的客户端
HTTP 协议本质上也就是基于 TCP 协议实现的,实现一个 HTTP 客户端/服务器,本质上也就是基于 TCP socket 进行封装
Qt 只是提供了 HTTP 客户端而没有提供 HTTP 服务器的库
关键类主要是三个,QNetworkAccessManager,QNetworkRequest,QNetworkReply
ONetworkAccessManager 提供了 HTTP 的核心操作
QNetworkRequest 表示一个 HTTP 请求(不含 body)
如果需要发送一个带有 body 的请求(比如 post),会在 QNetworkAccessManager 的 post 方法中通过单独的参数来传入 body
- QVariant,类似于 C 语言中的 void*,表示一个"类型可变"的值其中的
- QNetworkRequest::KnownHeaders是一个枚举类型,常用取值:
QNetworkReply 表示一个 HTTP 响应,这个类同时也是 QIODevice 的子类
此外,QNetworkReply 还有一个重要的信号 finished,会在客户端收到完整的响应数据之后触发
因为显示的响应结果大概率是一个 HTML,为了能够看到响应的原始模样,下面图形化界面的方式创建 QPlainTextEdit 来进行表示
另一个 QTextEdit (天然支持对 HTML 的解析的)
但是会对 HTML 进行解析渲染,最终显示的效果,就不是原始的 HTML
QTextEdit 背后还做了很多工作,当得到的 HTML 比较大的时候,也会造成卡顿
在 widget.h 中创建成员 manager:
widget.cpp 中构造函数如下:
发送按钮的槽函数:
运行程序,输入 http://www.baidu.com,点击发送,效果为:
上述就拿到了百度主页包含的元素了
Qt:网络编程到此结束