文章目录
- [4. Qt 网络](#4. Qt 网络)
-
- [4.1 UDP Socket](#4.1 UDP Socket)
-
- [4.1.1 API](#4.1.1 API)
- [4.1.2 回显服务器(UDP)](#4.1.2 回显服务器(UDP))
- [4.1.3 回显客户端(UDP)](#4.1.3 回显客户端(UDP))
- [4.2 TCP Socket](#4.2 TCP Socket)
-
- [4.2.1 API](#4.2.1 API)
- [4.2.2 回显服务器(TCP)](#4.2.2 回显服务器(TCP))
- [4.2.3 回显客户端(TCP)](#4.2.3 回显客户端(TCP))
- [4.3 HTTP Client](#4.3 HTTP Client)
-
- [4.3.1 核心 API](#4.3.1 核心 API)
- [4.3.2 HTTP GET 请求](#4.3.2 HTTP GET 请求)
4. Qt 网络
Qt Network 是 Qt 框架中专门用于跨平台网络编程的核心模块,复杂的底层网络协议(如 TCP/UDP/HTTP)和操作系统原生的 socket API 封装成了易用的 C++ 类。
使用 Qt 网络模块时,需要在项目的 .pro 文件中添加一行配置,确保链接到网络库:
plaintext
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)
cpp
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)
cpp
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)
cpp
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)
cpp
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 常作为客户端/前端访问服务器,所以
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 请求
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()
{
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();
});
}
