Qt TCP/UDP 网络协议入门实操UDP通讯
Posted 火山上的企鹅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt TCP/UDP 网络协议入门实操UDP通讯相关的知识,希望对你有一定的参考价值。
源码: NetToolsTest
QT Widge 其它文章请点击这里: QT Widget 学习笔记
姊妹篇:
此文只是最简单的入门学习,需进一步可以看 飞扬青云 大佬的源码 QWidgetDemo, 选择 nettool ,已经是非常完善的网络调试助手了
UDP(User Datagram Protocol即用户数据报协议)是一个轻量级的,不可靠的,面向数据报的无连接协议。我们现在几乎每个人都使用的QQ,其聊天时就是使用UDP协议进行消息发送的。就像QQ那样,当有很多用户,发送的大部分都是短消息,要求能及时响应,并且对安全性要求不是很高的情况下使用UDP协议。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。所以qq这种对保密要求并不太高的聊天程序就是使用的UDP协议。
在Qt中提供了QUdpSocket 类来进行UDP数据报(datagrams)的发送和接收。这里我们还要了解一个名词Socket,也就是常说的“套接字”。Socket简单地说,就是一个IP地址加一个port端口 。因为我们要传输数据,就要知道往哪个机子上传送,而IP地址确定了一台主机,但是这台机子上可能运行着各种各样的网络程序,我们要往哪个程序中发送呢?这时就要使用一个端口来指定UDP程序。所以说,Socket指明了数据报传输的路径。
此段摘自:浅谈 Qt 中 UDP 之 UdpSocket通信实例
一、UDP 服务器
在Qt 中使用UDP 客户端通讯演示如下:
● 实操流程图
● 代码
udpclinet.cpp
#include "udpclinet.h"
#include "ui_udpclinet.h"
UdpClinet::UdpClinet(QWidget *parent) :
QWidget(parent),
ui(new Ui::UdpClinet)
{
ui->setupUi(this);
initForm();
}
UdpClinet::~UdpClinet()
{
delete ui;
}
//1. UI
//2. 初始化
//① 创建 QTcpSocket 套接字对象
//② 建立socket 接收缓冲数据的信号槽(readyRead)
void UdpClinet::initForm()
{
socket = new QUdpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
//3. 接收UDP数据
void UdpClinet::readData()
{
QHostAddress host;
quint16 port;
QByteArray data;
while (socket->hasPendingDatagrams()) {
data.resize(socket->pendingDatagramSize());
socket->readDatagram(data.data(), data.size(), &host, &port);
QString str = QString("[%1:%2] %3").arg(host.toString()).arg(port).arg(QString(data));
ui->txtMain->setTextColor(QColor("red"));
ui->txtMain->append(str);
}
}
//4. 发送UDP数据 (socket->connectToHost)
// 在连接按键中,获取手动输入的服务器IP地址和端口号
void UdpClinet::on_btnSend_clicked()
{
UdpServerIP = ui->txtServerIP->text().trimmed();
UdpServerPort = ui->txtServerPort->text().trimmed().toInt();
QString data = ui->cboxData->currentText();
if (data.length() <= 0) {
return;
}
QByteArray buffer = data.toUtf8();
socket->writeDatagram(buffer, QHostAddress(UdpServerIP), UdpServerPort);
QString str = QString("[发送:%1:%2] %3").arg(UdpServerIP).arg(UdpServerPort).arg(data);
ui->txtMain->setTextColor(QColor("darkgreen"));
ui->txtMain->append(str);
}
udpclinet.h
#ifndef UDPCLINET_H
#define UDPCLINET_H
#include <QWidget>
#include <QtNetwork>
namespace Ui {
class UdpClinet;
}
class UdpClinet : public QWidget
{
Q_OBJECT
public:
explicit UdpClinet(QWidget *parent = nullptr);
void initForm();
~UdpClinet();
private:
Ui::UdpClinet *ui;
QUdpSocket *socket;
QString UdpServerIP;
int UdpServerPort;
private slots:
void readData();
private slots:
void on_btnSend_clicked();
};
#endif // UDPCLINET_H
二、UDP 服务器
在Qt 中使用UDP 服务器通讯演示如下:
● 实操流程图
● 代码
udpserver.cpp
#include "udpserver.h"
#include "ui_udpserver.h"
UdpServer::UdpServer(QWidget *parent) :
QWidget(parent),
ui(new Ui::UdpServer)
{
ui->setupUi(this);
initForm();
}
UdpServer::~UdpServer()
{
delete ui;
}
//1. ui
//2. 初始化
//① 创建 QUdpSocket 套接字对象
//② 建立socket 接收缓冲数据的信号槽(readyRead)
void UdpServer::initForm()
{
socket = new QUdpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
//3.开启监听, IP不指定,端口自定义
void UdpServer::on_btnListen_clicked()
{
UdpServerPort = ui->txtListenPort->text().trimmed().toInt();
if (ui->btnListen->text() == "监听") {
if (socket->bind(QHostAddress::AnyIPv4, UdpServerPort)) {
ui->btnListen->setText("关闭");
}
} else {
socket->abort();
ui->btnListen->setText("监听");
}
}
//4. 接收UDP客户端数据,获取UDP客户端IP和端口号,并保存到 listWidget 中
void UdpServer::readData()
{
QHostAddress host;
quint16 port;
QByteArray data;
while (socket->hasPendingDatagrams()) {
data.resize(socket->pendingDatagramSize());
socket->readDatagram(data.data(), data.size(), &host, &port);
//ip
QString ip = host.toString();
ip = ip.replace("::ffff:", "");
if (ip.isEmpty()) {
continue;
}
QString str = QString("[%1:%2] %3").arg(ip).arg(port).arg(QString(data));
ui->txtMain->setTextColor(QColor("red"));
ui->txtMain->append(str);
//添加到 listWidget 列表中
QString listData = QString("%1:%2").arg(ip).arg(port);
for (int i = 0; i < ui->listWidget->count(); i++) {
QString s = ui->listWidget->item(i)->text();
if (listData == s) {
return;
}
}
ui->listWidget->addItem(listData);
ui->labCount->setText(QString("%1个客户端").arg(ui->listWidget->count()));
}
}
//5. 发送数据到UDP客户端
// 利用已保存的客户端IP和端口号发送
void UdpServer::on_btnSend_clicked()
{
QString data = ui->cboxData->currentText();
if (data.length() <= 0) {
return;
}
int row = ui->listWidget->currentRow();
if (row >= 0) {
QString str = ui->listWidget->item(row)->text();
QStringList list = str.split(":");
QString ip = list.at(0);
quint16 port = list.at(1).toInt();
socket->writeDatagram(data.toUtf8(), QHostAddress(ip), port);
QString strPrint = QString("[%1:%2] %3").arg(ip).arg(port).arg(data);
ui->txtMain->setTextColor(QColor("darkgreen"));
ui->txtMain->append(strPrint);
}
}
udpserver.h
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QWidget>
#include <QtNetwork>
namespace Ui {
class UdpServer;
}
class UdpServer : public QWidget
{
Q_OBJECT
public:
explicit UdpServer(QWidget *parent = nullptr);
~UdpServer();
void initForm();
private:
Ui::UdpServer *ui;
QUdpSocket *socket;
int UdpServerPort;
private slots:
void readData();
private slots:
void on_btnListen_clicked();
void on_btnSend_clicked();
};
#endif // UDPSERVER_H
源码: NetToolsTest
QT Widge 其它文章请点击这里: QT Widget 学习笔记
姊妹篇:
以上是关于Qt TCP/UDP 网络协议入门实操UDP通讯的主要内容,如果未能解决你的问题,请参考以下文章