

文章目录
正文
某程序员深夜调试网络程序,突然发现数据包在传输中集体消失。他盯着屏幕喃喃自语:“我的数据包去哪了?难道它们也学会了早退?”——欢迎来到网络编程的奇妙世界!
1. QT网络模块:你的网络军火库
1.1 核心类全景图
QT的网络模块就像瑞士军刀:
- 传输层:QTcpSocket(TCP)、QUdpSocket(UDP)
- 应用层:QNetworkAccessManager(HTTP/FTP)
- 辅助类:QHostInfo(域名解析)、QNetworkProxy(网络代理)
1.2 第一个网络程序:时间服务器
// 获取世界时间
void fetchTime() {
QTcpSocket socket;
socket.connectToHost("time.nist.gov", 13); // 时间服务器端口
if (socket.waitForConnected(3000)) {
socket.waitForReadyRead();
qDebug() << "当前时间:" << socket.readAll();
} else {
qDebug() << "连接失败:" << socket.errorString();
}
}
运行结果:
当前时间:59338 22-10-18 12:34:56 UTC
1.3 网络状态检测
// 检测网络可达性
QNetworkConfigurationManager mgr;
if (mgr.isOnline()) {
qDebug() << "网络已连接";
} else {
qDebug() << "请检查网络连接!";
}
// 更精准的检测
QHostInfo::lookupHost("www.qt.io", [](const QHostInfo &host){
if (host.error())
qDebug() << "DNS解析失败:" << host.errorString();
else
qDebug() << "解析成功:" << host.addresses().first();
});
2. TCP编程:可靠的数据传输
2.1 TCP服务器搭建
// 简易聊天服务器
class ChatServer : public QTcpServer {
Q_OBJECT
public:
void start(quint16 port) {
connect(this, &QTcpServer::newConnection, this, [=]{
while (hasPendingConnections()) {
QTcpSocket *client = nextPendingConnection();
clients << client;
connect(client, &QTcpSocket::readyRead, [=]{
broadcast(client->readAll(), client);
});
}
});
listen(QHostAddress::Any, port);
}
private:
void broadcast(const QByteArray &msg, QTcpSocket *sender) {
for (auto client : clients) {
if (client != sender)
client->write("用户" + sender->peerAddress().toString().toUtf8() + "说: " + msg);
}
}
QList<QTcpSocket*> clients;
};
2.2 TCP客户端开发
// 带自动重连的客户端
class ReconnectClient : public QObject {
Q_OBJECT
public:
void connectToServer(QString host, quint16 port) {
socket = new QTcpSocket(this);
connect(socket, &QTcpSocket::connected, []{ qDebug() << "连接成功!"; });
connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
[=]{ QTimer::singleShot(5000, [=]{ connectToServer(host, port); });
});
socket->connectToHost(host, port);
}
private:
QTcpSocket *socket;
};
2.3 数据分包处理
// 处理粘包问题
void onReadyRead() {
while (socket->bytesAvailable()) {
if (!packetSize) {
if (socket->bytesAvailable() < sizeof(quint32)) return;
socket->read((char*)&packetSize, sizeof(quint32));
}
if (socket->bytesAvailable() < packetSize) return;
QByteArray data = socket->read(packetSize);
processPacket(data); // 处理完整数据包
packetSize = 0;
}
}
3. UDP编程:速度与激情
3.1 广播与组播
// 局域网广播
QUdpSocket udpSocket;
QByteArray datagram = "紧急通知:今晚服务器维护!";
// 广播到所有设备
udpSocket.writeDatagram(datagram, QHostAddress::Broadcast, 45454);
// 加入组播组
udpSocket.bind(QHostAddress::AnyIPv4, 45455, QUdpSocket::ReuseAddressHint);
udpSocket.joinMulticastGroup(QHostAddress("224.0.0.100"));
3.2 实时视频传输
// 视频帧传输示例
void sendVideoFrame(const QImage &frame) {
QByteArray block;
QBuffer buffer(&block);
buffer.open(QIODevice::WriteOnly);
frame.save(&buffer, "JPEG", 50); // 压缩质量50%
// 分片发送
const int chunkSize = 1024;
for (int i = 0; i < block.size(); i += chunkSize) {
QByteArray chunk = block.mid(i, chunkSize);
udpSocket.writeDatagram(chunk, peerAddress, port);
}
}
4. HTTP编程:Web世界的桥梁
4.1 GET与POST请求
// 带JSON处理的HTTP请求
QNetworkRequest createRequest(QUrl url) {
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Bearer xyz123");
return request;
}
void fetchUserData() {
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
QUrl url("https://api.example.com/users/123");
connect(nam, &QNetworkAccessManager::finished, [=](QNetworkReply *reply) {
if (reply->error() == QNetworkReply::NoError) {
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll());
qDebug() << "用户信息:" << doc.object()["name"].toString();
}
reply->deleteLater();
});
nam->get(createRequest(url)); // GET请求
}
void postLogin() {
QJsonObject json{{"username", "admin"}, {"password", "123456"}};
QByteArray data = QJsonDocument(json).toJson();
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
nam->post(createRequest(QUrl("https://api.example.com/login")), data);
}
4.2 文件下载器
// 带进度显示的下载器
class Downloader : public QObject {
Q_OBJECT
public:
void startDownload(QUrl url, QString savePath) {
file.setFileName(savePath);
file.open(QIODevice::WriteOnly);
reply = nam.get(QNetworkRequest(url));
connect(reply, &QNetworkReply::readyRead, [=]{
file.write(reply->readAll());
});
connect(reply, &QNetworkReply::downloadProgress,
[=](qint64 bytesReceived, qint64 bytesTotal){
qDebug() << "下载进度:" << bytesReceived * 100 / bytesTotal << "%";
});
connect(reply, &QNetworkReply::finished, [=]{
file.close();
if (reply->error()) {
qDebug() << "下载失败:" << reply->errorString();
file.remove();
} else {
qDebug() << "下载完成!";
}
reply->deleteLater();
});
}
private:
QNetworkAccessManager nam;
QNetworkReply *reply;
QFile file;
};
5. WebSocket:实时通信新宠
5.1 双向通信实现
// WebSocket客户端
QWebSocket socket;
socket.open(QUrl("ws://echo.websocket.org"));
connect(&socket, &QWebSocket::connected, []{
qDebug() << "WebSocket已连接!";
socket.sendTextMessage("Hello Server!");
});
connect(&socket, &QWebSocket::textMessageReceived, [](const QString &msg){
qDebug() << "收到消息:" << msg;
});
// 服务器端
QWebSocketServer server("EchoServer", QWebSocketServer::NonSecureMode);
server.listen(QHostAddress::Any, 1234);
connect(&server, &QWebSocketServer::newConnection, [&]{
QWebSocket *client = server.nextPendingConnection();
connect(client, &QWebSocket::textMessageReceived, [=](const QString &msg){
client->sendTextMessage("ECHO: " + msg);
});
});
6. 性能优化:让代码飞起来
6.1 连接池技术
// HTTP连接池
class HttpPool : public QObject {
public:
QNetworkAccessManager* getManager() {
if (pool.isEmpty()) {
return createManager();
}
return pool.takeFirst();
}
void releaseManager(QNetworkAccessManager* mgr) {
pool.append(mgr);
}
private:
QNetworkAccessManager* createManager() {
auto mgr = new QNetworkAccessManager(this);
// 配置代理、缓存等
return mgr;
}
QList<QNetworkAccessManager*> pool;
};
// 使用示例
HttpPool pool;
auto mgr = pool.getManager();
mgr->get(QNetworkRequest(QUrl("https://example.com")));
// 请求完成后
pool.releaseManager(mgr);
6.2 数据压缩传输
// Zlib压缩数据
QByteArray compressData(const QByteArray &data) {
QByteArray compressed = qCompress(data, 9); // 最高压缩级别
return compressed.toBase64(); // Base64编码便于传输
}
// 解压缩
QByteArray decompressData(const QByteArray &compressed) {
QByteArray decoded = QByteArray::fromBase64(compressed);
return qUncompress(decoded);
}
终极实战:开发局域网文件共享工具
核心功能:
- UDP广播发现在线设备
- TCP传输文件列表
- HTTP分块下载文件
- WebSocket实时聊天
// 设备发现广播
void broadcastPresence() {
QUdpSocket udp;
QJsonObject presence {
{"device_name", "MyPC"},
{"ip", getLocalIP()},
{"port", 8080}
};
udp.writeDatagram(QJsonDocument(presence).toJson(),
QHostAddress::Broadcast, 8888);
}
// 接收广播
void discoverDevices() {
udp.bind(8888, QUdpSocket::ShareAddress);
connect(&udp, &QUdpSocket::readyRead, [=]{
while (udp.hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udp.pendingDatagramSize());
udp.readDatagram(datagram.data(), datagram.size());
QJsonObject device = QJsonDocument::fromJson(datagram).object();
qDebug() << "发现设备:" << device["device_name"].toString();
}
});
}
最后:网络编程的终极法则
- 可靠性:TCP不保证100%送达,重要数据需确认机制
- 安全性:敏感数据必须加密(TLS/SSL)
- 可扩展性:使用协议缓冲区(Protocol Buffers)代替JSON
- 容错性:网络波动是常态,重试机制不可少
// 程序员宣誓
qDebug() << "我承诺:";
qDebug() << "1. 绝不阻塞主线程";
qDebug() << "2. 永远检查返回值";
qDebug() << "3. 处理所有异常状态";
qDebug() << "4. 写满注释(虽然从不写)";
结语
感谢您的阅读!期待您的一键三连!欢迎指正!


被折叠的 条评论
为什么被折叠?



