【QT】Qt网络


个人主页~


Qt系统相关

一、Qt网络

在进行网络编程之前,需要在项目中的.pro文件中添加network模块

实际开发中不会用Qt直接写服务器的,因为服务器是没有图形化界面的,一般我们会用其他的语言软件写好程序之后与Qt联合使用,这里只是演示

在实现网络编程的时候在pro文件中要加入network

1、UDP Socket

(1)核心API

方法 说明
bind(const QHostAddress&,quint16) 绑定指定的端口号
receiveDatagram 返回QNetworkDatagram,读取一个UDP数据报
writeDatagram(const QNetworkDatagram&) 发送一个UDP数据报
信号 说明
readyRead 在收到数据并准备就绪后触发
QNetworkDatagram
构造函数 说明
QNetworkDatagram(const QByteArray& ,const QHostAddress& ,quint16) 通过QByteArray,目标IP地址,目标端口号构造一个UDP数据报
方法 说明
data 获取数据报内部持有的数据,返回QByteArray
senderAddress 获取数据报中包含的对端的IP地址
senderPort 获取数据报中包含的对端的端口号

(2)回显服务器

回显服务器和回显客户端顾名思义就是我给服务器发送什么服务器给我发送什么

widget.cpp
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
	//修改窗口标题
    this->setWindowTitle("服务器");
    //创建udp实例
    socket = new QUdpSocket(this);
    //连接信号槽
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processRequest);
    //绑定端口
    bool ret = socket->bind(QHostAddress::Any,9090);
    if(!ret)
    {
        QMessageBox::critical(nullptr,"服务器启动有误",socket->errorString());
        return;
    }
}

void Widget::processRequest()
{
	//读取请求
    const QNetworkDatagram& requestDatagram = socket->receiveDatagram();
    //解析请求
    QString request = requestDatagram.data();
    //根据请求计算响应
    const QString& response = process(request);
    //响应回写客户端
    QNetworkDatagram responseDatagram(response.toUtf8(),requestDatagram.senderAddress(),requestDatagram.senderPort());
    socket->writeDatagram(responseDatagram);
    //交互信息显示到窗口上
    QString log = "[" + requestDatagram.senderAddress().toString() + ":" + QString::number(requestDatagram.senderPort())+"}req: "+request+",resp:"+response;
    ui->listWidget->addItem(log);
}

QString Widget::process(const QString &request)
{
	//对于回显服务器来说,请求就是回应,但是对于大型的商务服务器,这里的代码量是非常巨大的
    return request;
}

(3)回显客户端

widget.cpp
cpp 复制代码
const QString& SERVER_IP = "127.0.0.1";//客户端IP地址
const quint16 SERVER_PORT = 9090;//客户端端口号

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //实例
    socket = new QUdpSocket(this);
	//窗口名
    this->setWindowTitle("客户端");
    //信号槽连接
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processResponse);
}
//这个函数用来处理收到的响应
void Widget::processResponse()
{
	//读取解析响应
    const QNetworkDatagram& responseDatagram = socket->receiveDatagram();
    QString response = responseDatagram.data();
    //因为是回显服务器,直接将响应数据显示到界面上
    ui->listWidget->addItem("服务器:"+response);
}


void Widget::on_pushButton_clicked()
{
	//获取到输入框的内容	
    const QString& text = ui->lineEdit->text();
    //构造请求数据
    QNetworkDatagram requestDatagram(text.toUtf8(),QHostAddress(SERVER_IP),SERVER_PORT);
    //发送请求数据
    socket->writeDatagram(requestDatagram);
    //发送的请求添加到列表框
    ui->listWidget->addItem("客户端:"+text);
    //清空输入框内容
    ui->lineEdit->setText("");
}

qudpsocket

2、TCP Socket

(1)核心API

主要有两个核心类

QTcpServer
方法 说明
listen(const QHostAddress&,quint16 port) 绑定指定的地址和端口号,并开始监听
nextPendingConnection 从系统中获取到一个已经建立好的tcp连接,返回一个QTcpSocket,表示这个客户端的连接,通过这个socket对象完成和客户端之间的通信
信号 说明
newConnection 有新的客户端建立好之后触发
QTcpSocket
方法 说明
readAll 读取当前接收缓冲区中的所有数据并返回一个QByteArray对象
write(const QByteArray&) 把数据写入socket中
deleteLater 暂时把socket对象标记为无效,Qt会在下个事件循环中析构释放该对象
信号 说明
readyRead 有数据到达准备就绪时触发
disconnected 断开连接时触发

(2)回显服务器

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 修改窗口标题.
    this->setWindowTitle("服务器");

    // 2. 创建 QTcpServer 的实例
    tcpServer = new QTcpServer(this);

    // 3. 通过信号槽, 指定如何处理连接.
    connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);

    // 4. 绑定并监听端口号. 一定要确保准备工作充分了, 再真正开张营业.
    //    这个操作得是初始化的最后一步. 都是需要把如何处理连接, 如何处理请求... 都准备好之后, 才能真正绑定端口并监听.
    bool ret = tcpServer->listen(QHostAddress::Any, 9090);
    if (!ret) {
        QMessageBox::critical(this, "服务器启动失败!", tcpServer->errorString());
        exit(1);
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processConnection()
{
    //通过tcpServer获得socket对象, 通过这个对象来和客户端进行通信
    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();
    QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] 客户端上线!";
    ui->listWidget->addItem(log);

    //通过信号槽, 来处理客户端发来请求的情况
    connect(clientSocket, &QTcpSocket::readyRead, this, [=]() {
        //读取出请求数据. 此处 readAll 返回的是 QByteArray, 通过赋值转成 QString
        QString request = clientSocket->readAll();
        //根据请求处理响应
        const QString& response = process(request);
        //把响应写回到客户端
        clientSocket->write(response.toUtf8());
        //把上述信息记录到日志中
        QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] "
                + " req: " + request + ", resp: " + response;
        ui->listWidget->addItem(log);
    });

    //通过信号槽处理客户端断开连接情况
    connect(clientSocket, &QTcpSocket::disconnected, this, [=]() {
        //断开连接信息通过日志打印
        QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] 客户端下线!";
        ui->listWidget->addItem(log);
        //手动释放 clientSocket. 使用deleteLater更加合适
        clientSocket->deleteLater();
    });
}

//回显服务器.
QString Widget::process(const QString request)
{
    return request;
}

(3)回显客户端

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置窗口标题
    this->setWindowTitle("客户端");
    //创建socket实例
    socket = new QTcpSocket(this);
    //和服务器连接
    socket->connectToHost("127.0.0.1", 9090);
    //连接信号槽, 处理响应
    connect(socket, &QTcpSocket::readyRead, [=]() {
        // 读取出响应内容
        QString response = socket->readAll();
        // 把响应内容显示到界面上
        ui->listWidget->addItem("服务器说: " + response);
    });
    // 等待连接建立的结果. 确认是否连接成功
    bool ret = socket->waitForConnected();
    if (!ret) {
        QMessageBox::critical(this, "连接服务器出错", socket->errorString());
        exit(1);
    }
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    // 获取到输入框中的内容
    const QString& text = ui->lineEdit->text();
    // 发送数据给服务器
    socket->write(text.toUtf8());
    // 把发的消息显示到界面上
    ui->listWidget->addItem("客户端说: " + text);
    // 清空输入框的内容
    ui->lineEdit->setText("");
}

qtcpsocket

3、HTTP Client

QNetworkAccessManager

提供核心操作

方法 说明
get(const QNetworkRequest& ) 发起一个HTTP GET请求,返回QNetworkReply对象
post(const QNetworkRequest& ,const QByteArray& ) 发起一个HTTP POST请求,返回QNetworkReply对象
QNetworkRequest

表示一个HTTP请求,不含body,body是数据本体

方法 说明
QNetworkRequest(const QUrl& ) 通过URL构造一个HTTP请求
setHeader(QNetworkRequest::KnowHeaders header,const QVariant& value) 设置请求头
QNetworkReply
方法 说明
error 获取出错状态
errorString 获取出错原因的文本
readAll 读取响应body
header(QNetworkRequest::KnownHeaders header) 读取相应指定header的值
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    manager = new QNetworkAccessManager(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    //获取到输⼊框中的URL, 构造QUrl对象
    QUrl url(ui->lineEdit->text());
    //构造HTTP请求对象
    QNetworkRequest request(url);
    //发送GET请求
    QNetworkReply* response = manager->get(request);
    //通过信号槽来处理响应
    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->deleteLater();
    });
}

qhttp


今日分享就到这里了~

相关推荐
初晴~8 分钟前
【动态规划】打家劫舍类问题
java·数据结构·c++·python·算法·leetcode·动态规划
翔云API35 分钟前
PHP开发示例-vin码识别接口-引领汽车行业数字化新风向
开发语言·php
ac-er888835 分钟前
如何对PHP的API接口权限认证
开发语言·php
菜鸟、小高36 分钟前
从0开始学PHP面向对象内容之(常用魔术方法续一)
开发语言·php
IT199538 分钟前
Linux笔记-对Linux环境变量的进一步认识(2024-08-09)
linux·运维·笔记·运维开发
cleveryuoyuo42 分钟前
红黑树分析
c++
yezipi耶不耶1 小时前
Rust 所有权机制
开发语言·后端·rust
B1nna2 小时前
SpringMVC学习记录(三)之响应数据
java·学习·json·springmvc·jsp
javachen__2 小时前
从美国大选,看软件安全风险与挑战
网络·安全·web安全
六月悉茗3 小时前
【C语言 - 简易架构】
c语言·开发语言