Python 实现udp组播

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 实现udp组播相关的知识,希望对你有一定的参考价值。

参考技术A 有关知识
基本概念
单播:两个主机间单对单的通信
广播:一个主机对整个局域网上所有主机上的数据通信(网络地址全1)
单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网的主机进行通信

组播:实际情况下,经常需要对一组特定的主机进行通信,而不是所有局域网上的主机
IP组播(也称多址广播或多播),是一种允许一台或多台主机发送数据包到多台主机的TCP/IP网路技术。

多播是 IPv6 数据包的 3 种基本目的地址类型之一,多播是一点对多点的通信, IPv6 没有采用 IPv4 中的组播术语,而是将广播看成是多播的一个特殊例子。

多播组只能用UDP 或者原始套接字实现,不能用TCP。

广播地址
在使用TCP/IP 协议的网络中,主机标识段host ID 为全1 的IP 地址为广播地址,广播的分组传送给host ID段所涉及的所有计算机。

传输层只有UDP可以广播 。

组播地址
IP 组播通信必须依赖于 IP 多播地址,在 IPv4 中它是一个 D 类 IP 地址,范围从 224.0.0.0 到 239.255.255.255,并被划分为局部链接多播地址、预留多播地址和管理权限多播地址3类:

局部链接多播地址范围在 224.0.0.0~224.0.0.255,这是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包;

预留多播地址为 224.0.1.0~238.255.255.255,可用于全球范围(如Internet)或网络协议;

管理权限多播地址为 239.0.0.0~239.255.255.255,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围。

组播地址与MAC地址的映射
使用同一个 IP 多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。

这个我们可以这样理解,多播地址就类似于 QQ 群号,多播组相当于 QQ 群,一个个的主机就相当于群里面的成员。

设备驱动程序就必须接收所有多播数据帧,然后对它们进行过滤,这个过滤过程是网络驱动或IP层自动完成。(设备驱动程序会对多播数据进行过滤,将其发到相应的位置)

组播应用
单点对多点应用
点对多点应用是指一个发送者,多个接收者的应用形式,这是最常见的多播应用形式。典型的应用包括:媒体广播、媒体推送、信息缓存、事件通知和状态监视等。

多点对单点应用
多点对点应用是指多个发送者,一个接收者的应用形式。通常是双向请求响应应用,任何一端(多点或点)都有可能发起请求。典型应用包括:资源查找、数据收集、网络竞拍、信息询问等。

多点对多点应用
多点对多点应用是指多个发送者和多个接收者的应用形式。通常,每个接收者可以接收多个发送者发送的数据,同时,每个发送者可以把数据发送给多个接收者。典型应用包括:多点会议、资源同步、并行处理、协同处理、远程学习、讨论组、分布式交互模拟(DIS)、多人游戏等。
参考的文章 https://www.cnblogs.com/schips/p/12552534.html

下面实现一个python(3.8)的演示原理的版本
功能:1.每个客户端随机生成一个id当做标识
2.每个客户端绑定本机一个Ip的端口(在同一台机器上面可以启动多个脚本)
3. 加入同一网段的一个组播地址
4. 启动后,发送一个消息
5. 收到消息后,根据id判断消息是否是自己发出的,其它客户端的时候回一个消息

启动两个脚本以后效果如下:

ps:在相同网段可以很容易实现组播。跨网段组播必须打开三层交换机的组播路由协议,一般是PIM 稀疏模式,一般三层交换机的默认配置是没有打开组播路由的。(待实践)

QT的UDP组播技术

一 UDP介绍

UDP是一种简单轻量级的传输层协议,提供无连接的,不可靠的报文传输。适合下面4种情况:

网络数据大多为短消息。

拥有大量客户端。

对数据安全性无特殊要求

网络负担非常重,但对响应速度要求高。

二 基于udp协议的c/s编程模型(广播),组播的话,明天再看。

客户端:

class Sender : public QObject
{
    Q_OBJECT //可以使用信号和槽
public:
    explicit Sender(QObject *parent = 0);
    ~Sender();//虚构函数无返回值
    void start();
public slots:
    void broadcastDatagram();

private:
    QUdpSocket *udpSocket;//包含 <QtNetwork/qudpsocket.h>
    QTimer *timer;
    int messageNo;


};

在使用udp tcp时,qt的.pro文件中要加上 QT    +=network.

具体实现:

#include "sender.h"

Sender::Sender(QObject *parent) :
    QObject(parent)
{
    timer = new QTimer(this);
    udpSocket = new QUdpSocket(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(broadcastDatagram()));
    messageNo = 1;
}
void Sender::start()
{
    timer->start(1000);
}
void Sender::broadcastDatagram()
{
    qDebug()<<(tr("Begin Broadcast: %1").arg(messageNo));
    QByteArray datagram = "BroadCast Message:" + QByteArray::number(messageNo);
    udpSocket->writeDatagram(datagram.data(),datagram.size(),QHostAddress::Broadcast,44444);
    ++messageNo;
}

Sender::~Sender()
{
    delete timer;
    delete udpSocket;//是否删除connect?
        
}

  udpSocket->writeDatagram(datagram.data(),datagram.size(),QHostAddress::Broadcast,44444);
函数原型:writeDatagram(const char* data,qint64 size,const QHostAddress &address,quint16 port)
函数功能:将数据包发出
函数参数:数据包自身,数据包大小,发送到的地址,端口。

 

 

接收端:

class Receiver : public QObject
{
    Q_OBJECT
public:
    explicit Receiver(QObject *parent = 0);
    ~Receiver();
signals:

public slots:
    void processPendingDatagrams();
private:
    QUdpSocket *udpSocket;

};

具体实现:

#include "receiver.h"

Receiver::Receiver(QObject *parent) :
    QObject(parent)
{
    udpSocket = new QUdpSocket(this);
    udpSocket->bind(44444);
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
}
void Receiver::processPendingDatagrams()
{
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());
        qDebug() << (tr("Receice Data: \"%1\"").arg(datagram.data()));
    }
}
Receiver::~Receiver()
{
    delete udpSocket;
}

当接受到数据包时,QUdpSocket会发出readyRead()信号。我关联了processPendingDatagrams()。

先用hasPendingDatagrams()判断是否有可供读取的数据。若有,则用pendingDatagramSize()开辟一个缓冲区。

最后,用readDatagram()将报文读取到缓冲区中。

以上是关于Python 实现udp组播的主要内容,如果未能解决你的问题,请参考以下文章

win7如何设允许udp组播

udp 协议 如何实现 局域网 一对多的通信?他们对应的原理是啥?腾讯qq 是用tcp还是udp?求教高手详解谢谢

UDP实现群聊聊天室

python3使用udp的方法

Python3组播通信编程实现教程(发送者+接收者)

win11接收udp组播