[Qt][Qt 网络][下]具体讲解

打印 上一主题 下一主题

主题 345|帖子 345|积分 1035


1.TCP Socket

1.核心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.回显服务器

  1. // 构造函数中
  2. {
  3.         server = new QTcpServer(this);
  4.         // 通过信号槽, 指定如何处理连接.
  5.         connect(server, &QTcpServer::newConnection,
  6.                         this, &Widget::ProcessConnection);
  7.        
  8.         // 绑定并监听端口号
  9.         if (!ret = server->listen(QHostAddress::Any, 2333))
  10.         {
  11.             QMessageBox::critical(this, "服务器启动失败!", server->errorString());
  12.             exit(1);
  13.         }
  14. }
  15. void Widget::ProcessConnection()
  16. {
  17.     // 通过 server 拿到一个 socket 对象, 通过这个对象来和客户端进行通信
  18.     QTcpSocket* clientSocket = tcpServer->nextPendingConnection();
  19.    
  20.     QString log = "[" + clientSocket->peerAddress().toString() + ":" +
  21.                                 QString::number(clientSocket->peerPort()) + "] 客户端上线!";
  22.     ui->listWidget->addItem(log);
  23.     // 通过信号槽, 来处理客户端发来请求的情况
  24.     connect(clientSocket, &QTcpSocket::readyRead, this, [=]() {
  25.         // a) 读取出请求数据,此处 readAll 返回的是 QByteArray, 通过赋值转成 QString
  26.         QString request = clientSocket->readAll();
  27.         
  28.         // b) 根据请求处理响应
  29.         const QString& response = Process(request);
  30.         
  31.         // c) 把响应写回到客户端
  32.         clientSocket->write(response.toUtf8());
  33.         
  34.         // d) 把上述信息记录到日志中.
  35.         QString log = "[" + clientSocket->peerAddress().toString() + ":" +
  36.                                     QString::number(clientSocket->peerPort()) + "] "
  37.                                 + " req: " + request + ", resp: " + response;
  38.         ui->listWidget->addItem(log);
  39.     });
  40.     // 通过信号槽, 来处理客户端断开连接的情况.
  41.     connect(clientSocket, &QTcpSocket::disconnected, this, [=]() {
  42.         // a) 把断开连接的信息通过日志显示出来.
  43.         QString log = "[" + clientSocket->peerAddress().toString() + ":" +
  44.                             QString::number(clientSocket->peerPort()) + "] 客户端下线!";
  45.         ui->listWidget->addItem(log);
  46.         
  47.         // b) 手动释放 clientSocket. 直接使用 delete 是下策, 使用 deleteLater 更加合适
  48.         clientSocket->deleteLater();
  49.     });
  50. }
  51. QString Widget::Process(const QString request)
  52. {
  53.     return request;
  54. }
复制代码

3.回显客户端

  1. // 构造函数中
  2. {
  3.         socket = new QTcpSocket(this);
  4.        
  5.         // 服务器建立连接,此处是非阻塞的IO通信
  6.         socket->connectToHost("127.0.0.1", 2333);
  7.        
  8.         // 连接信号槽, 处理响应
  9.         connect(socket, &QTcpSocket::readyRead, this, [=]() {
  10.             // a) 读取出响应内容
  11.             QString response = socket->readAll();
  12.             
  13.             // b) 把响应内容显示到界面上.
  14.             ui->listWidget->addItem("服务器说: " + response);
  15.         });
  16.        
  17.         // 等待连接建立的结果. 确认是否连接成功.
  18.         if (!socket->waitForConnected())
  19.         {
  20.             QMessageBox::critical(this, "连接服务器出错", socket->errorString());
  21.             exit(1);
  22.         }
  23. }
  24. void Widget::on_pushButton_clicked()
  25. {
  26.     const QString& text = ui->lineEdit->text();
  27.    
  28.     socket->write(text.toUtf8());
  29.    
  30.     ui->listWidget->addItem("客户端说: " + text);
  31.     ui->lineEdit->setText("");
  32. }
复制代码

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():为一个信号,在客⼾端收到完整的相应数据之后触发

  • 示例
    1. // 构造函数中
    2. {
    3.     manager = new QNetworkAccessManager(this);
    4. }
    5. void Widget::on_pushButton_clicked()
    6. {
    7.     // 1. 获取到输入框中的 url
    8.     QUrl url(ui->lineEdit->text());
    9.    
    10.     // 2. 构造一个 HTTP 请求对象
    11.     QNetworkRequest request(url);
    12.    
    13.     // 3. 发送请求
    14.     QNetworkReply* response = manager->get(request);
    15.    
    16.     // 4. 通过信号槽, 来处理响应
    17.     connect(response, &QNetworkReply::finished, this, [=]() {
    18.         if (response->error() == QNetworkReply::NoError)
    19.         {
    20.             QString html = response->readAll();
    21.             ui->plainTextEdit->setPlainText(html);
    22.         }
    23.         else
    24.         {
    25.             ui->plainTextEdit->setPlainText(response->errorString());
    26.         }
    27.         
    28.         // 需要对 response 进行手动释放.
    29.         response->deleteLater();
    30.     });
    31. }
    复制代码

3.其他模块



  • Qt中还提供了FTP,DNS,SSL等⽹络相关的组件⼯具,有必要可以具体学习,查阅官方文档

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表