1.QUdpSocket

UDP是轻量的、不可靠的、面向数据报、无连接的协议,它可以用于对可靠性要求不高的场合,与TCP通信不同,无需建立持久的socket连接。

QUdpSocket用于实现UDP通信,与QTcpSocket主要区别是,QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数据使用writeDatagram(),数据报的长度一般少于512字节,每个数据报包含发送者和接收者的IP地址和端口等信息。

要进行UDP通信,首先需要bind函数绑定一个端口,用于接收传入的手机不能。当有数据报传入时会发射readyRead()信号,使用readDatagram()来读取接收到的数据报。

UDP消息传送有单播、广播、组播三种模式。

  • 单播:一个UDP客户端发出的数据报只发送到另一个指定地址和端口的UDP客户端,是一对一的数据传输。
  • 广播:一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以收到。
  • 组播:也称多播,UDP客户端加入到另一个组播IP地址指定的多播组,成员向组播地址发送的数据报组内成员都可以接收到,类似于QQ群功能。

在单播、广播和多播下,UDP程序都是对等的,不像TCP那样分为客户端和服务器端。单播和广播的实现方式基本相同,只是数据报的目标IP地址设置不同,多播模式需要加入多播组,实现方式有较大差异。

2.单播/广播

本机运行两个实例需要绑定不同的端口,例如实例A绑定端口2000,实例B绑定端口3000,实例A向实例B发送数据时,需要指定实例B所在主机的IP地址、绑定端口作为目标地址和目标端口,这样实例B才能接收到数据报。如果在不同的计算机运行,则可以使用相同的端口。

  • 要实现数据接收,必须先使用QUdpSocket::bind()绑定一个端口,用于监听传入的数据报。解除绑定则使用abort()函数。
  • writeDatagram()函数向一个目标用户发送消息时,需要指定目标地址和端口。
  • 在广播消息时,只需要将目标地址更换为一个特殊地址,即广播地址QHostAddress::Broadcast,一般为255.255.255.255
  • 发送的数据报是QByteArray类型的字节数组,数据报的长度一般不超过512字节,可以是文本,也可以是二进制数据。
  • 接收到数据报后会发射readyRead()信号。
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QUdpSocket>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_btnBind_clicked();void on_btnUnBind_clicked();void on_btnClear_clicked();void on_btnQuit_clicked();void on_btnSend_clicked();void on_btnBroadcast_clicked();void on_readyRead();
private:Ui::Widget *ui;private:QUdpSocket *m_udpSocket = nullptr;
};#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QHostInfo>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//本地主机名QString hostName = QHostInfo::localHostName();//本机IP地址QHostInfo hostInfo = QHostInfo::fromName(hostName);//IP地址列表QList<QHostAddress> addrList = hostInfo.addresses();for(int i=0;i<addrList.count();i++){QHostAddress host = addrList.at(i);if(QAbstractSocket::IPv4Protocol == host.protocol()){QString ip = host.toString();ui->comboBox->addItem(ip);}}m_udpSocket = new QUdpSocket(this);connect(m_udpSocket,&QUdpSocket::readyRead,this,&Widget::on_readyRead);}Widget::~Widget()
{delete ui;
}void Widget::on_btnBind_clicked()
{//本机UDP端口qint16 port = ui->spinBindPort->value();if(m_udpSocket->bind(port)){ui->plainTextEdit->appendPlainText("**已成功绑定");ui->plainTextEdit->appendPlainText("**绑定端口: "+QString::number(m_udpSocket->localPort()));ui->btnBind->setEnabled(false);ui->btnUnBind->setEnabled(true);}else{ui->plainTextEdit->appendPlainText("**绑定失败");}
}void Widget::on_btnUnBind_clicked()
{//解除绑定m_udpSocket->abort();ui->btnBind->setEnabled(true);ui->btnUnBind->setEnabled(false);ui->plainTextEdit->appendPlainText("**已解除绑定");
}void Widget::on_btnClear_clicked()
{ui->plainTextEdit->clear();
}void Widget::on_btnQuit_clicked()
{}void Widget::on_btnSend_clicked()//单播
{//目标IPQString dstIp = ui->comboBox->currentText();QHostAddress dstAddr(dstIp);//目标端口quint16 dstPort = ui->spinDstPort->value();QString msg = ui->lineEdit->text();QByteArray str = msg.toUtf8();//发出数据报m_udpSocket->writeDatagram(str,dstAddr,dstPort);ui->plainTextEdit->appendPlainText("[out] "+msg);
}void Widget::on_btnBroadcast_clicked()//广播
{quint16 dstPort = ui->spinDstPort->value();QString msg = ui->lineEdit->text();QByteArray str = msg.toUtf8();//发出数据报m_udpSocket->writeDatagram(str,QHostAddress::Broadcast,dstPort);ui->plainTextEdit->appendPlainText("[Broadcast] "+msg);
}void Widget::on_readyRead()
{//是否还有待读取的传入数据报while(m_udpSocket->hasPendingDatagrams()){QByteArray data;//返回待读取的数据报的字节数data.resize(m_udpSocket->pendingDatagramSize());QHostAddress peerAddr;quint16 peerPort;//读取数据报的内容m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);QString str = data.data();QString peer = "[From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";ui->plainTextEdit->appendPlainText(peer+str);}
}

3.组播

组播是主机之间“一对一组”的通信模式,当多个客户端加入由一个组播地址定义的多播组之后,客户端向组播地址和端口发送数据报,组内成员都可以接收到,类似QQ群。

UDP组播必须使用一个组播地址。组播地址是D类IP地址,有特定的地址段。多播组可以是永久的也可以是临时的。永久多播组保持不变的是它的IP地址,组内成员结构可以发生变化。

  • 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其他地址供路由协议使用
  • 224.0.1.0~224.0.1.255是公用组播地址,可以用于internet
  • 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效
  • 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效

若在家庭或办公室局域网内测试UDP组播功能,可以使用组播地址范围是239.0.0.0~239.255.255.255

joinMulticastGroup()函数使主机加入一个多播组,leaveMulticastGroup()函数使主机离开一个多播组。

UDP组播的特点是使用组播地址,其他的端口绑定、数据报收发功能与单播UDP完全相同。

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QUdpSocket>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_btnClear_clicked();void on_btnSend_clicked();void on_readyRead();void on_btnJoin_clicked();void on_btnExit_clicked();private:Ui::Widget *ui;private:QUdpSocket *m_udpSocket = nullptr;QHostAddress groupAddr; //组播地址
};#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QHostInfo>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//本地主机名QString hostName = QHostInfo::localHostName();m_udpSocket = new QUdpSocket(this);//socket QAbstractSocket::MulticastTtlOption值为1,MulticastTtlOption是//组播的数据的生存期,数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播m_udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);connect(m_udpSocket,&QUdpSocket::readyRead,this,&Widget::on_readyRead);}Widget::~Widget()
{delete ui;
}void Widget::on_btnClear_clicked()
{ui->plainTextEdit->clear();
}void Widget::on_btnSend_clicked()//组播
{//目标端口quint16 groupPort = ui->spinBindPort->value();QString msg = ui->lineEdit->text();QByteArray str = msg.toUtf8();//发出数据报m_udpSocket->writeDatagram(str,groupAddr,groupPort);ui->plainTextEdit->appendPlainText("[multicast] "+msg);
}void Widget::on_readyRead()
{while(m_udpSocket->hasPendingDatagrams()){QByteArray data;data.resize(m_udpSocket->pendingDatagramSize());QHostAddress peerAddr;quint16 peerPort;m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);QString str = data.data();QString peer = "[From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";ui->plainTextEdit->appendPlainText(peer+str);}
}void Widget::on_btnJoin_clicked()
{QString IP = ui->comboBox->currentText();groupAddr = QHostAddress(IP);quint16 groupPort = ui->spinBindPort->value();//加入组播之前,必须先绑定端口,端口为多播组统一的一个端口。if(m_udpSocket->bind(QHostAddress::AnyIPv4,groupPort,QUdpSocket::ShareAddress)){//加入组播m_udpSocket->joinMulticastGroup(groupAddr);ui->plainTextEdit->appendPlainText("**加入组播成功");ui->plainTextEdit->appendPlainText("**组播IP: "+ IP);ui->plainTextEdit->appendPlainText("**绑定端口: "+QString::number(groupPort));ui->btnJoin->setEnabled(false);ui->btnExit->setEnabled(true);ui->comboBox->setEnabled(false);}else{ui->plainTextEdit->appendPlainText("**绑定端口失败");}
}void Widget::on_btnExit_clicked()
{//退出组播m_udpSocket->leaveMulticastGroup(groupAddr);//解除绑定m_udpSocket->abort();ui->btnJoin->setEnabled(true);ui->btnExit->setEnabled(false);ui->comboBox->setEnabled(true);ui->plainTextEdit->appendPlainText("**已退出组播");
}

相关推荐:UDP多线程Server

QT UDP通信(单播、广播、组播)相关推荐

  1. 单播 广播 组播_【技术解析】关于组播概念那些你需要知道的~

    点击蓝字关注我 今天,小盟带大家继续学习一下组播知识~ 一.IGMP Message 1.组成员一旦开启IGMP,会自动发送Membership Report消息到叶路由器 2.IGMPv2版本,组成 ...

  2. 单播 广播 组播_组播概念3

    一.IGMP Message 1.组成员一旦开启IGMP,会自动发送Membership Report消息到叶路由器 2.IGMPv2版本,组成员退出组会发送leave消息,IGMPv1不会 3.也就 ...

  3. 单播 广播 组播区别

    一:通信方式分类 在IPv4网络中,主机可采用的通信方式有如下三种: 1.单播:单台主机与单台主机之间的数据通信 带宽端口有多少台就发多少个数据 2.广播:单台主机向网络中所有主机发送数据包的过程 发 ...

  4. HCIA-RS自用笔记(9)数据转发过程、单播/多播/组播

    数据转发过程(7/13,29min) 网关(Gateway) 不同网络的主机需要通讯,首先要把数据转发给网关,网关代表一条缺省路由 查看Windows主机路由表: C:\Users\Admin> ...

  5. 单播,组播,广播的区别

    单播,组播,广播的区别 单播"(Unicast)."多播"(Multicast)和"广播"(Broadcast)这三个术语都是用来描述网络节点之间通讯 ...

  6. Java实现单播,组播,广播

    单播.组播.广播介绍:https://blog.csdn.net/ahou2468/article/details/86526509 目录 1.单播.组播.广播关键类说明 2.单播和广播的具体实现 2 ...

  7. IP网络通信的单播、组播和广播

    一.判断两台设备是否在同一局域网内 查看两台设备的ip4地址和子网掩码MASK. 若MASK不一样,则不在同一局域网内. 若MASK一样,分别计算IP&MASK.若二者相同,则在同一局域网,否 ...

  8. 单播、组播、广播三者之间的区别

    单播.组播.广播其实是IPv4定义的三种流量类型 - 单播流量:一个人发送

  9. 【TCP/IP】单播与组播

    [TCP/IP]单播与组播 三种IP地址: 单播地址.广播地址和组播地址 广播和多播仅应用于UDP. TCP是一个面向连接的协议,TCP一定是点对点的,一点是两个主机来建立连接的,TCP肯定是单播.只 ...

  10. 判断mac地址单播还是组播(shell脚本)

    MAC地址是以太网二层使用的一个48bit(6字节十六进制数)的地址,用来标识设备位置.MAC地址分成两部分,前24位是组织唯一标识符(OUI, Organizationally unique ide ...

最新文章

  1. hadoop容灾能力测试
  2. xxx in ‘Anonymous class derived from xxx clashes with ‘call(T)‘ in xxx attempting to use incompati
  3. 是否可以将 json 反序列化为 dynamic 对象?
  4. KVM复制虚拟机,KVM克隆虚拟机
  5. 张文宏:WHO新型冠状病毒的传言和事实
  6. 【IDEA】关于 IDEA 中新建 web 项目的 webapp 文件夹没有小蓝点 ,启动服务,访问不到解决方案
  7. openresty lua集成kafka
  8. Memcache与Redis的区别
  9. 最新csdn有奖任务答案
  10. MATLAB小技巧(28)模糊综合评价
  11. 鉴源实验室丨车载ECU嵌入式软件的测试入门
  12. DIY一款600元成本的电路板热成像故障分析仪
  13. crt测试显示器软件,MonitorTest(显示器性能测试软件)
  14. Python类传参报错-TypeError:takes 2 positional arguments but 3 were given
  15. Java将OFD文件转PDF文件
  16. 百度智能云OCR获取APIKey和SecretKey
  17. qt 频谱 音乐播放器
  18. 传统优化方法:枚举法、启发式算法和搜索算法
  19. Spring入门-1-基本配置和IOC、DI
  20. 1.1、SR(Segment Routing Over MPLS) 介绍

热门文章

  1. 如何在 R 中的直方图上叠加正态曲线(2 个示例)
  2. rl滤波器原理_滤波器基本知识
  3. 中国企业管理水平啥时候才能成熟啊
  4. matlab的kron函数(kronecker乘积)
  5. 数据可视化实战:数据可视化
  6. Science:拟南芥根系三萜化合物塑造特异的微生物组
  7. Mybatis CRUD操作和多表查询
  8. 台式计算机如何自动开关机,台式机怎么设置自动开关机
  9. 各大IT公司往届校招笔试面试题汇总
  10. Hibernate(6)——映射类型