使用udp组播原因:
????????想要实现查找局域网自己的设备,但是不知道存在设备的ip;
????????局域网软件在线更新,不想固定服务器的ip地址,因为是开发人员电脑,ip可能随时在变化;
? ? ? ? 比较了广播、组播的优缺点,最终选择组播;
组播优点:
????????组播技术的初衷是在IP网络中,以"尽力而为"的形式发送信息到某个目标组,这个目标组称为组播组,这样在有源主机向多点目标主机发送信息需求时,源主机只发送一份数据,数据的目的地址是组播组地址,这样,凡是属于该组的成员,都可以接收到一份源主机发送的数据的拷贝,此组播方式下,只有真正信息需要的成员会收到信息,其他主机不会收到。组播方式解决了单播情况下数据的重复拷贝及带宽的重复占用,也解决了广播方式下带宽资源的浪费。
组播地址:(所以我们使用239.0.0.0~239.255.255.255最合适)
????????组播组可以是永久的也可以是临时的。组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的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为本地管理组播地址,仅在特定的本地范围内有效。
实际qt代码:
注意:同一个程序里面,发送组播ip和接收组播ip分开,也就是一个用来接收别人的消息,一个用来发送消息给别人;端口号也分别使用两个;
使用前需要做的:
//包含头文件之前请在项目pro文件中添加
QT += network
//在要使用的地方添加头文件
#include <QUdpSocket>
#include <QHostInfo>
#include <QNetworkInterface>
1、初始化
void ****** ::Start()
{
//创建组播发送
QUdpSocket c_SenderUdpSocket4.bind(QHostAddress(QHostAddress::AnyIPv4), 0);
c_SenderUdpSocket4.setSocketOption(QAbstractSocket::MulticastTtlOption, 10);//10表示发送的消息可以被转发10次
//创建组播接收
QUdpSocket c_ReceiverUdpSocket4.bind(QHostAddress::AnyIPv4, 23901, QUdpSocket::ShareAddress);
c_ReceiverUdpSocket4.joinMulticastGroup(QHostAddress(239.239.239.230));
connect(&c_ReceiverUdpSocket4, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));//绑定接收响应函数
//获取本机第一个ipv4的ip地址(这个地址一般来说就是本机ip地址)
auto HostAddressList = QNetworkInterface::allAddresses();
for (auto i = HostAddressList.begin(); i != HostAddressList.end(); i++) {
if (i->protocol() == QAbstractSocket::IPv4Protocol)
{
c_LocalAddress = (*i).toString();
break;
}
}
//设置定时器,定时发送组播数据
c_timer = new QTimer(this);
connect(c_timer, SIGNAL(timeout()), this, SLOT(TimerOut()));
c_timer->start(500);
}
2、超时响应函数
void ******::TimerOut()
{
//就是定时发送组播信息
QString datagram("Is anyone there?Give me your IP.My IP is 192.168.1.111");
c_SenderUdpSocket4.writeDatagram(datagram.toStdString().c_str(),datagram.size(), QHostAddress("239.239.239.231"), 23910);
}
3、接收响应函数
void ******::processPendingDatagrams()
{
QByteArray datagram;
// using QUdpSocket::readDatagram (API since Qt 4)
while (c_ReceiverUdpSocket4.hasPendingDatagrams()) {
datagram.resize(int(c_ReceiverUdpSocket4.pendingDatagramSize()));
c_ReceiverUdpSocket4.readDatagram(datagram.data(), datagram.size());
// Received IPv4 datagram
emit ReceiveUdpGroupData(datagram.constData());
}
QString Data(datagram.constData());
/*
这里处理接收到的数据
如果一个组很多人同时发送数据过来,记得自己拆分
*/
//一般接收到数据后是自己需要的就停止定时发送数据,基本这里就获取到我们想要的数据了;
//比如你收到的“192.168.1.111,i'm waiting for you,My IP is 192.168.2.222”
c_timer->stop();
// using QUdpSocket::receiveDatagram (API since Qt 5.8)
// while (udpSocket6.hasPendingDatagrams()) {
// QNetworkDatagram dgram = udpSocket6.receiveDatagram();
// statusLabel->setText(statusLabel->text() +
// tr("\nReceived IPv6 datagram from [%2]:%3: \"%1\"")
// .arg(dgram.data().constData(), dgram.senderAddress().toString())
// .arg(dgram.senderPort()));
// }
}
最后:
? ? ? ? 这样一操作,哈哈你是不是就知道对方ip了,对方也知道你的ip了,剩下的就自由发挥了,基本上udp组播的使命到这里就结束了,剩下的就交给其他人吧,不能逮着一个人霍霍啊,还是要雨露均沾的。
如有不正确或者不足之处还望各位指正!
|