[Qt][Qt 网络][下]详细讲解
DieSnowK 2024-08-22 08:37:01 阅读 62
目录
1.TCP Socket1.核心API概览2.回显服务器3.回显客户端
2.HTTP Client3.其他模块
1.TCP Socket
1.核心API概览
核⼼类是两个:<code>QTcpServer和QTcpSocket
QTcpServer
用于监听端口,和获取客户端连接
listen(const QHostAddress&, quint16 port)
:绑定指定的地址和端⼝号,并开始监听
成员方法对标原⽣API:bind()
和listen()
nextPendingConnection()
:从系统中获取到⼀个已经建⽴好的tcp连接
返回⼀个QTcpSocket
,表⽰这个客⼾端的连接
通过这个socket对象完成和客⼾端之间的通信 成员方法对标原⽣API:accept()
newConnection()
:有新的客⼾端建⽴连接好之后触发
信号类似于IO多路复用的通知机制 QTcpSocket
⽤于客⼾端和服务器之间的数据交互
readAll()
:读取当前接收缓冲区中的所有数据,返回QByteArray
对象
成员方法对标原生API:read()
write(const QByteArray &)
:把数据写⼊socket中
成员方法对标原生API:write()
deleteLater()
:暂时把socket对象标记为⽆效,Qt会在下个事件循环中析构释放该对象
成员方法类似于"半⾃动化的垃圾回收" readyRead()
:有数据到达并准备就绪时触发
信号类似于IO多路复⽤中的通知机制 disconnected()
:连接断开时触发
信号类似于IO多路复⽤中的通知机制
2.回显服务器
// 构造函数中
{
server = new QTcpServer(this);
// 通过信号槽, 指定如何处理连接.
connect(server, &QTcpServer::newConnection,
this, &Widget::ProcessConnection);
// 绑定并监听端口号
if (!ret = server->listen(QHostAddress::Any, 2333))
{
QMessageBox::critical(this, "服务器启动失败!", server->errorString());
exit(1);
}
}
void Widget::ProcessConnection()
{
// 通过 server 拿到一个 socket 对象, 通过这个对象来和客户端进行通信
QTcpSocket* clientSocket = tcpServer->nextPendingConnection();
QString log = "[" + clientSocket->peerAddress().toString() + ":" +
QString::number(clientSocket->peerPort()) + "] 客户端上线!";
ui->listWidget->addItem(log);
// 通过信号槽, 来处理客户端发来请求的情况
connect(clientSocket, &QTcpSocket::readyRead, this, [=]() {
// a) 读取出请求数据,此处 readAll 返回的是 QByteArray, 通过赋值转成 QString
QString request = clientSocket->readAll();
// b) 根据请求处理响应
const QString& response = Process(request);
// c) 把响应写回到客户端
clientSocket->write(response.toUtf8());
// d) 把上述信息记录到日志中.
QString log = "[" + clientSocket->peerAddress().toString() + ":" +
QString::number(clientSocket->peerPort()) + "] "
+ " req: " + request + ", resp: " + response;
ui->listWidget->addItem(log);
});
// 通过信号槽, 来处理客户端断开连接的情况.
connect(clientSocket, &QTcpSocket::disconnected, this, [=]() {
// a) 把断开连接的信息通过日志显示出来.
QString log = "[" + clientSocket->peerAddress().toString() + ":" +
QString::number(clientSocket->peerPort()) + "] 客户端下线!";
ui->listWidget->addItem(log);
// b) 手动释放 clientSocket. 直接使用 delete 是下策, 使用 deleteLater 更加合适
clientSocket->deleteLater();
});
}
QString Widget::Process(const QString request)
{
return request;
}
3.回显客户端
// 构造函数中
{
socket = new QTcpSocket(this);
// 服务器建立连接,此处是非阻塞的IO通信
socket->connectToHost("127.0.0.1", 2333);
// 连接信号槽, 处理响应
connect(socket, &QTcpSocket::readyRead, this, [=]() {
// a) 读取出响应内容
QString response = socket->readAll();
// b) 把响应内容显示到界面上.
ui->listWidget->addItem("服务器说: " + response);
});
// 等待连接建立的结果. 确认是否连接成功.
if (!socket->waitForConnected())
{
QMessageBox::critical(this, "连接服务器出错", socket->errorString());
exit(1);
}
}
void Widget::on_pushButton_clicked()
{
const QString& text = ui->lineEdit->text();
socket->write(text.toUtf8());
ui->listWidget->addItem("客户端说: " + text);
ui->lineEdit->setText("");
}
2.HTTP Client
Qt只提供了Http客户端,并没有提供Http服务端的库关键类主要是三个:QNetworkAccessManager
, QNetworkRequest
, QNetworkReply
QNetworkAccessManager
提供了HTTP的核⼼操作
get(const QNetworkRequest&)
:发起⼀个HTTP GET请求,返回QNetworkReply
对象
本身不是阻塞函数,只负责发出去请求,不负责等请求回来收是QNetworkReply
负责的,会收到finished
信号 post(const QNetworkRequest&, const QByteArray&)
:发起⼀个HTTP POST请求,返回QNetworkReply
对象 QNetworkRequest
表⽰⼀个HTTP请求(不含body),如果需要发送⼀个带有body的请求(⽐如post
),会在QNetworkAccessManager
的post()
中通过单独的参数来传⼊body
QNetworkRequest(const QUrl&)
:通过URL构造⼀个HTTP请求setHeader(QNetworkRequest::KnownHeaders header, const QVariant& value)
:设置请求头
QNetworkRequest::KnownHeaders
是⼀个枚举类型,常⽤取值
ContentTypeHeader
:描述body的类型ContentLengthHeader
:描述body的⻓度LocationHeader
:⽤于重定向报⽂中指定重定向地址CookieHeader
:设置cookieUserAgentHeader
:设置User-Agent QNetworkReply
表⽰⼀个HTTP响应,这个类同时也是QIODevice
的⼦类
error()
:获取出错状态errorString()
:获取出错原因的⽂本readAll()
:读取响应bodyheader(QNetworkRequest::KnownHeaders header)
:读取响应指定header的值finished()
:为一个信号,在客⼾端收到完整的响应数据之后触发 示例:
// 构造函数中
{
manager = new QNetworkAccessManager(this);
}
void Widget::on_pushButton_clicked()
{
// 1. 获取到输入框中的 url
QUrl url(ui->lineEdit->text());
// 2. 构造一个 HTTP 请求对象
QNetworkRequest request(url);
// 3. 发送请求
QNetworkReply* response = manager->get(request);
// 4. 通过信号槽, 来处理响应
connect(response, &QNetworkReply::finished, this, [=]() {
if (response->error() == QNetworkReply::NoError)
{
QString html = response->readAll();
ui->plainTextEdit->setPlainText(html);
}
else
{
ui->plainTextEdit->setPlainText(response->errorString());
}
// 需要对 response 进行手动释放.
response->deleteLater();
});
}
3.其他模块
Qt中还提供了FTP,DNS,SSL等⽹络相关的组件⼯具,有需要可以具体学习,查阅官方文档
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。