[Qt][Qt 网络][下]具体讲解
1.TCP Socket1.核心API概览
[*]核⼼类是两个: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:设置cookie
[*]UserAgentHeader:设置User-Agent
[*]QNetworkReply表⽰⼀个HTTP相应,这个类同时也是QIODevice的⼦类
[*]error():获取出错状态
[*]errorString():获取出错缘故原由的⽂本
[*]readAll():读取相应body
[*]header(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等⽹络相关的组件⼯具,有必要可以具体学习,查阅官方文档
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]