欢迎光临
我们一直在努力

Qt 网络:包含Udp、Tcp、Http三种协议的客户端实践手册

文章目录

  • 4. Qt 网络
    • 4.1 UDP Socket
      • 4.1.1 API
      • 4.1.2 回显服务器(UDP)
      • 4.1.3 回显客户端(UDP)
    • 4.2 TCP Socket
      • 4.2.1 API
      • 4.2.2 回显服务器(TCP)
      • 4.2.3 回显客户端(TCP)
    • 4.3 HTTP Client
      • 4.3.1 核心 API
      • 4.3.2 HTTP GET 请求

4. Qt 网络

Qt Network 是 Qt 框架中专门用于跨平台网络编程的核心模块,复杂的底层网络协议(如 TCP/UDP/HTTP)和操作系统原生的 socket API 封装成了易用的 C++ 类。

使用 Qt 网络模块时,需要在项目的 .pro 文件中添加一行配置,确保链接到网络库:

QT += network

4.1 UDP Socket

  • QUdpSocket:UDP 套接字,负责绑定端口、收发数据报。
  • QNetworkDatagram:UDP 数据报,封装数据、目标地址、端口等。

4.1.1 API

QUdpSocket 核心方法/信号

名称说明
bind(const QHostAddress& addr, quint16 port) 绑定地址和端口
receiveDatagram() 读取一个 UDP 数据报,返回 QNetworkDatagram
writeDatagram(const QNetworkDatagram& datagram) 发送 UDP 数据报
readyRead 收到数据时触发

QNetworkDatagram 核心方法

名称说明
QNetworkDatagram(const QByteArray& data, const QHostAddress& addr, quint16 port) 构造数据报(数据、目标地址、端口)
data() 获取数据报内容(返回 QByteArray)
senderAddress() 获取发送方 IP 地址
senderPort() 获取发送方端口号

4.1.2 回显服务器(UDP)

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

this->setWindowTitle("服务端");
//创建套接字
socket=new QUdpSocket(this);
//绑定信号槽
connect(socket,&QUdpSocket::readyRead,this,&Widget::handlerudp);
//绑定端口号
if(socket->bind(QHostAddress::Any,8080)==false)
{
QMessageBox::critical(this,"服务器启动错误",socket->errorString());
}
}

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

void Widget::handlerudp()
{
auto handlerresponse = [&](const QString& req){
return "resp:"+req;
};
//1.读取请求
const QNetworkDatagram& requestDatagarm=socket->receiveDatagram();
QString request=requestDatagarm.data();
//2.处理请求
const QString& response= handlerresponse(request);
//3.发回请求
socket->writeDatagram(QNetworkDatagram(response.toUtf8(),requestDatagarm.senderAddress(),requestDatagarm.senderPort()));

ui->listWidget->addItem("[" + requestDatagarm.senderAddress().toString() + ":"
+ QString::number(requestDatagarm.senderPort())
+ "] req: " + request + ", resp: " + response);
}

4.1.3 回显客户端(UDP)

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

socket=new QUdpSocket(this);

this->setWindowTitle("客户端");
ui->pushButton->setShortcut(QKeySequence(Qt::Key_Return | Qt::Key_Enter));

connect(ui->lineEdit, &QLineEdit::returnPressed, ui->pushButton, &QPushButton::click);
connect(socket, &QUdpSocket::readyRead, this, &Widget::handlerres);
}

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

void Widget::on_pushButton_clicked()
{
QString str=ui->lineEdit->text();
ui->lineEdit->setText("");

ui->listWidget->addItem("发送: "+str);
//构建发送请求
QNetworkDatagram requestDatagram(str.toUtf8(),QHostAddress("127.0.0.1"),8080);
socket->writeDatagram(requestDatagram);
}

void Widget::handlerres()
{
const QNetworkDatagram& recieveDatagarm=socket->receiveDatagram();
QString request=recieveDatagarm.data();

ui->listWidget->addItem("收到: "+ request);
}

在这里插入图片描述

4.2 TCP Socket

  • QTcpServer:服务器端,负责监听端口、接收客户端连接。
  • QTcpSocket:客户端/服务器端通信套接字,负责数据读写。

4.2.1 API

QTcpServer 核心方法/信号

名称说明对标原生 API
listen(const QHostAddress& addr, quint16 port) 绑定地址端口并开始监听 bind + listen
nextPendingConnection() 获取已建立的客户端连接(返回 QTcpSocket*) accept
newConnection 有新客户端连接时触发

QTcpSocket 核心方法/信号

名称说明对标原生 API
readAll() 读取接收缓冲区所有数据(返回 QByteArray) read
write(const QByteArray& data) 写入数据到套接字 write
deleteLater() 标记对象待销毁,下一个事件循环释放
readyRead 收到数据时触发
disconnected 连接断开时触发
connectToHost(const QString& addr, quint16 port) 客户端连接服务器 connect

4.2.2 回显服务器(TCP)

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

this->setWindowTitle("服务端");

tcpserver();
}

void Widget::tcpserver()
{
//创建套接字
tcpsocket=new QTcpServer(this);
//绑定信号槽
connect(tcpsocket,&QTcpServer::newConnection,this,&Widget::handlertcp);
//绑定端口号
if(tcpsocket->listen(QHostAddress::Any,8080)==false)
{
QMessageBox::critical(this,"服务器启动错误",tcpsocket->errorString());
}

}

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

void Widget::handlertcp()
{
//获得socket对象,通过这个与客户端进行通信
QTcpSocket* clientSocket = tcpsocket->nextPendingConnection();
//绑定信号槽
connect(clientSocket,&QTcpSocket::readyRead,this,[=](){
auto handlerresponse = [&](const QString& req){
return "resp:"+req;
};
//1.读取请求
QString request=clientSocket->readAll();
//2.处理请求
const QString& response= handlerresponse(request);
//3.发回请求
clientSocket->write(response.toUtf8());

ui->listWidget->addItem("[" + clientSocket->peerAddress().toString() + ":"
+ QString::number(clientSocket->peerPort())
+ "] req: " + request + ", resp: " + response);
});

//处理断开连接
connect(clientSocket,&QTcpSocket::disconnected,this,[=](){
ui->listWidget->addItem("[" + clientSocket->peerAddress().toString() + ":"
+ QString::number(clientSocket->peerPort())
+ "] 连接断开");

clientSocket->deleteLater();//将缓冲区内存读取完毕再销毁,better than 直接delete
});
}

4.2.3 回显客户端(TCP)

Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

this->setWindowTitle("客户端");
ui->pushButton->setShortcut(QKeySequence(Qt::Key_Return | Qt::Key_Enter));

connect(ui->lineEdit, &QLineEdit::returnPressed, ui->pushButton, &QPushButton::click);
//handlerudpres();
handlertcpres();
}

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

void Widget::on_pushButton_clicked()
{
auto sendudp=[=](const QString& str){
QNetworkDatagram requestDatagram(str.toUtf8(),QHostAddress("127.0.0.1"),8080);
udpsocket->writeDatagram(requestDatagram);
};

auto sendtcp=[=](const QString& str){
tcpsocket->write(str.toUtf8());
};

QString str=ui->lineEdit->text();
ui->lineEdit->setText("");

ui->listWidget->addItem("发送: "+str);
//构建发送请求
sendtcp(str);

}

void Widget::handlertcpres()
{
tcpsocket=new QTcpSocket(this);
//与服务器建立连接(非阻塞)
tcpsocket->connectToHost("127.0.0.1",8080);
//判断建立结果
if( tcpsocket->waitForConnected()==false)
{
QMessageBox::critical(this,"服务器启动错误",tcpsocket->errorString());
}

connect(tcpsocket, &QTcpSocket::readyRead, this, [=](){

QString request=tcpsocket->readAll();

ui->listWidget->addItem("收到: "+ request);
});

}

在这里插入图片描述

4.3 HTTP Client

Qt 通过 QNetworkAccessManager、QNetworkRequest、QNetworkReply 类实现 HTTP 通信,支持 GET、POST 等请求。由于 Qt 常作为客户端/前端访问服务器,所以着重介绍 HTTP Client 。

4.3.1 核心 API

QNetworkAccessManager 核心方法

方法说明
get(const QNetworkRequest& request) 发起 HTTP GET 请求,返回 QNetworkReply*
post(const QNetworkRequest& request, const QByteArray& data) 发起 HTTP POST 请求,返回 QNetworkReply*

QNetworkRequest 核心方法

方法说明
QNetworkRequest(const QUrl& url) 通过 URL 构造请求
setHeader(QNetworkRequest::KnownHeaders header, const QVariant& value) 设置请求头(如 Content-Type、User-Agent)

QNetworkRequest::KnownHeaders 常用取值

取值说明
ContentTypeHeader 请求体类型(如 application/json)
ContentLengthHeader 请求体长度
CookieHeader Cookie 信息
UserAgentHeader 客户端标识(User-Agent)

QNetworkReply 核心方法/信号

方法/信号说明
error() 获取请求错误状态(QNetworkReply::NoError 为成功)
errorString() 获取错误描述
readAll() 读取响应体数据
header(QNetworkRequest::KnownHeaders header) 读取响应头
finished() 请求完成(成功/失败)时触发

4.3.2 HTTP GET 请求

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()
{
QString url=ui->lineEdit->text();
//构造http请求
QNetworkRequest request(url);
//发送请求
QNetworkReply* response=manager->get(request);
//信号槽处理
connect(response,&QNetworkReply::finished,this,[=](){
//判断是否出错
if(response->error()==QNetworkReply::NoError)
{
QString html=response->readAll();//一般访问到的都是html
ui->listWidget->addItem(html);
}
else
{
QMessageBox::critical(this,"服务器启动错误",response->errorString());
}

response->deleteLater();
});
}

在这里插入图片描述

赞(0)
未经允许不得转载:171主机测评 » Qt 网络:包含Udp、Tcp、Http三种协议的客户端实践手册
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址