当前位置:首页 » 《关于电脑》 » 正文

[Qt][Qt 网络][下]详细讲解

14 人参与  2024年09月07日 10:46  分类 : 《关于电脑》  评论

点击全文阅读


目录

1.TCP Socket1.核心API概览2.回显服务器3.回显客户端 2.HTTP Client3.其他模块


1.TCP Socket

1.核心API概览

核⼼类是两个:QTcpServerQTcpSocketQTcpServer用于监听端口,和获取客户端连接 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 , QNetworkReplyQNetworkAccessManager提供了HTTP的核⼼操作 get(const QNetworkRequest&):发起⼀个HTTP GET请求,返回QNetworkReply对象 本身不是阻塞函数,只负责发出去请求,不负责等请求回来收是QNetworkReply负责的,会收到finished信号 post(const QNetworkRequest&, const QByteArray&):发起⼀个HTTP POST请求,返回QNetworkReply对象 QNetworkRequest表⽰⼀个HTTP请求(不含body),如果需要发送⼀个带有body的请求(⽐如post),会在QNetworkAccessManagerpost()中通过单独的参数来传⼊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等⽹络相关的组件⼯具,有需要可以具体学习,查阅官方文档

点击全文阅读


本文链接:http://zhangshiyu.com/post/156559.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1