https://blog.csdn.net/only_write_bug/article/details/159115776?spm1011.2415.3001.5331目录一、组播介绍二、组播初始化和使用1、创建QUdpSocket对象2、绑定本地端口3、加入组播组4、发送组播数据5、接收组播数据6、离开组播组三、为什么需要指定网卡如何绑定固定网卡1、如何查看自己电脑有那些网卡信息2、如何查找自己电脑对应IP的网卡信息以及绑定一、组播介绍组播Multicast是一种高效的网络通信方式它允许将数据包同时发送给一组特定的接收者而无需为每个接收者都复制一份数据。组播地址IPv4组播地址范围是224.0.0.0~239.255.255.255D类地址。其中224.0.0.0~224.0.0.255为本地链路组播地址如224.0.0.1表示所有子网主机通常不被应用程序使用239.0.0.0~239.255.255.255为管理权限组播地址私有组播地址适合内部网络使用。组播组加入同一个组播地址的所有主机形成一个组播组。发送者只需将数据发往组播地址路由器会负责将数据复制到有接收者的链路上。相关链接https://blog.csdn.net/only_write_bug/article/details/159115776?spm1011.2415.3001.5331二、组播初始化和使用1、创建QUdpSocket对象QUdpSocket *udpSocket new QUdpSocket(this);2、绑定本地端口// ShareAddress 允许共享地址。如前所述允许多个套接字绑定到同一地址和端口// ReuseAddressHint: 提示地址重用。为套接字提供一个“提示”告诉它即使地址和端口正被另一个套接字使用也应尝试重新绑定。// ShareAddress和ReuseAddressHint通常一起使用这里绑定到QHostAddress::AnyIPv4表示监听所有网络接口上的指定端口。如果希望只监听特定网卡可以传入该网卡的IP地址。udpSocket-bind(QHostAddress::AnyIPv4, 12345, QUdpSocket::ShareAddress);这里为绑定到特定IP地址和端口selfip为QString对象所以需要转换为QHostAddress。selfip和port为你需要绑定的ip和端口。if (!udpSocket-bind(QHostAddress(selfip), myport, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { qWarning() Failed to bind status socket: m_socket-errorString(); }3、加入组播组QHostAddress multicastAddr(239.255.43.21); udpSocket-joinMulticastGroup(multicastAddr);多个网卡的情况下你已知自己需要绑定的网卡名称可直接绑定到对应网卡。如下QNetworkInterface interface QNetworkInterface::interfaceFromName(eth0); udpSocket-joinMulticastGroup(multicastAddr, interface);4、发送组播数据发送方不需要加入组播组只需将数据报的目的地址设为组播地址即可。发送前建议设置组播数据包的TTL生存时间udpSocket-setSocketOption(QAbstractSocket::MulticastTtlOption, 1); // TTL1 限制在本地子网 udpSocket-writeDatagram(datagram.data(), datagram.size(), multicastAddr, 12345);5、接收组播数据当有数据到达绑定的端口时QUdpSocket会发出readyRead()信号在槽函数中读取connect(udpSocket, QUdpSocket::readyRead, this, [](){ while (udpSocket-hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket-pendingDatagramSize()); QHostAddress sender; quint16 senderPort; udpSocket-readDatagram(datagram.data(), datagram.size(), sender, senderPort); // 处理数据或者定义信号将数据传到其他线程进行处理... } });6、离开组播组当你的程序不再需要接收组播信息时应该先离开组播组udpSocket-leaveMulticastGroup(multicastAddr);三、为什么需要指定网卡如何绑定固定网卡当你调用udpSocket-bind(QHostAddress::AnyIPv4, 12345, QUdpSocket::ShareAddress);绑定任意IP信息时如果你的电脑只有一个网卡的话问题不大但是如果有多个网卡就会出现接收不到信息的问题因为电脑组播在接收数据流的时候可能会切换到其他网卡接收导致组播接收数据出现丢失但是不会影响你的组播信息发送。所以在电脑有多网卡或者有虚拟环境的时候推荐组播绑定到特定的网卡。1、如何查看自己电脑有那些网卡信息添加QNetworkInterface QNetworkDatagram头文件之后可调用QT的 QNetworkInterface::allInterfaces()查看目前你的电脑可用的所有网卡信息。如果你已知你的网卡信息就不需要。QString info Available network interfaces; qDebug()info; foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) { if (iface.flags() QNetworkInterface::IsUp iface.flags() QNetworkInterface::IsRunning !(iface.flags() QNetworkInterface::IsLoopBack)) { info Interface: iface.name() Human readable: iface.humanReadableName(); qDebug()info; foreach (QNetworkAddressEntry entry, iface.addressEntries()) { if (entry.ip().protocol() QAbstractSocket::IPv4Protocol) { info IP: entry.ip().toString(); qDebug()info; } } } }2、如何查找自己电脑对应IP的网卡信息以及绑定self为自身IP信息。QNetworkInterface m_multicastIface; if (!selfip.isEmpty()) { const auto interfaces QNetworkInterface::allInterfaces(); for (const QNetworkInterface iface : interfaces) //遍历所有网卡信息 { for (const QNetworkAddressEntry entry : iface.addressEntries()) //遍历所有IP地址 { if (entry.ip().toString() selfip)//找到对应IP信息 { m_multicastIface iface; qDebug() 找到匹配网卡: iface.humanReadableName() IP: selfip; break; } } if (m_multicastIface.isValid()) break; } } //加入组播组 if (m_multicastIface.isValid()) { if (m_socket-joinMulticastGroup(groupAddress, m_multicastIface)) { qDebug() 通过网卡 m_multicastIface.humanReadableName() 加入组播组成功; // 设置组播发送的接口确保发送也走同一网卡 可不设置 udpsocket-setMulticastInterface(m_multicastIface); } else{ qWarning() 指定网卡加入组播组失败: udpsocket-errorString(); } }
QT组播的建立和使用(绑定特定的网卡,绑定特定IP)
https://blog.csdn.net/only_write_bug/article/details/159115776?spm1011.2415.3001.5331目录一、组播介绍二、组播初始化和使用1、创建QUdpSocket对象2、绑定本地端口3、加入组播组4、发送组播数据5、接收组播数据6、离开组播组三、为什么需要指定网卡如何绑定固定网卡1、如何查看自己电脑有那些网卡信息2、如何查找自己电脑对应IP的网卡信息以及绑定一、组播介绍组播Multicast是一种高效的网络通信方式它允许将数据包同时发送给一组特定的接收者而无需为每个接收者都复制一份数据。组播地址IPv4组播地址范围是224.0.0.0~239.255.255.255D类地址。其中224.0.0.0~224.0.0.255为本地链路组播地址如224.0.0.1表示所有子网主机通常不被应用程序使用239.0.0.0~239.255.255.255为管理权限组播地址私有组播地址适合内部网络使用。组播组加入同一个组播地址的所有主机形成一个组播组。发送者只需将数据发往组播地址路由器会负责将数据复制到有接收者的链路上。相关链接https://blog.csdn.net/only_write_bug/article/details/159115776?spm1011.2415.3001.5331二、组播初始化和使用1、创建QUdpSocket对象QUdpSocket *udpSocket new QUdpSocket(this);2、绑定本地端口// ShareAddress 允许共享地址。如前所述允许多个套接字绑定到同一地址和端口// ReuseAddressHint: 提示地址重用。为套接字提供一个“提示”告诉它即使地址和端口正被另一个套接字使用也应尝试重新绑定。// ShareAddress和ReuseAddressHint通常一起使用这里绑定到QHostAddress::AnyIPv4表示监听所有网络接口上的指定端口。如果希望只监听特定网卡可以传入该网卡的IP地址。udpSocket-bind(QHostAddress::AnyIPv4, 12345, QUdpSocket::ShareAddress);这里为绑定到特定IP地址和端口selfip为QString对象所以需要转换为QHostAddress。selfip和port为你需要绑定的ip和端口。if (!udpSocket-bind(QHostAddress(selfip), myport, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint)) { qWarning() Failed to bind status socket: m_socket-errorString(); }3、加入组播组QHostAddress multicastAddr(239.255.43.21); udpSocket-joinMulticastGroup(multicastAddr);多个网卡的情况下你已知自己需要绑定的网卡名称可直接绑定到对应网卡。如下QNetworkInterface interface QNetworkInterface::interfaceFromName(eth0); udpSocket-joinMulticastGroup(multicastAddr, interface);4、发送组播数据发送方不需要加入组播组只需将数据报的目的地址设为组播地址即可。发送前建议设置组播数据包的TTL生存时间udpSocket-setSocketOption(QAbstractSocket::MulticastTtlOption, 1); // TTL1 限制在本地子网 udpSocket-writeDatagram(datagram.data(), datagram.size(), multicastAddr, 12345);5、接收组播数据当有数据到达绑定的端口时QUdpSocket会发出readyRead()信号在槽函数中读取connect(udpSocket, QUdpSocket::readyRead, this, [](){ while (udpSocket-hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket-pendingDatagramSize()); QHostAddress sender; quint16 senderPort; udpSocket-readDatagram(datagram.data(), datagram.size(), sender, senderPort); // 处理数据或者定义信号将数据传到其他线程进行处理... } });6、离开组播组当你的程序不再需要接收组播信息时应该先离开组播组udpSocket-leaveMulticastGroup(multicastAddr);三、为什么需要指定网卡如何绑定固定网卡当你调用udpSocket-bind(QHostAddress::AnyIPv4, 12345, QUdpSocket::ShareAddress);绑定任意IP信息时如果你的电脑只有一个网卡的话问题不大但是如果有多个网卡就会出现接收不到信息的问题因为电脑组播在接收数据流的时候可能会切换到其他网卡接收导致组播接收数据出现丢失但是不会影响你的组播信息发送。所以在电脑有多网卡或者有虚拟环境的时候推荐组播绑定到特定的网卡。1、如何查看自己电脑有那些网卡信息添加QNetworkInterface QNetworkDatagram头文件之后可调用QT的 QNetworkInterface::allInterfaces()查看目前你的电脑可用的所有网卡信息。如果你已知你的网卡信息就不需要。QString info Available network interfaces; qDebug()info; foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) { if (iface.flags() QNetworkInterface::IsUp iface.flags() QNetworkInterface::IsRunning !(iface.flags() QNetworkInterface::IsLoopBack)) { info Interface: iface.name() Human readable: iface.humanReadableName(); qDebug()info; foreach (QNetworkAddressEntry entry, iface.addressEntries()) { if (entry.ip().protocol() QAbstractSocket::IPv4Protocol) { info IP: entry.ip().toString(); qDebug()info; } } } }2、如何查找自己电脑对应IP的网卡信息以及绑定self为自身IP信息。QNetworkInterface m_multicastIface; if (!selfip.isEmpty()) { const auto interfaces QNetworkInterface::allInterfaces(); for (const QNetworkInterface iface : interfaces) //遍历所有网卡信息 { for (const QNetworkAddressEntry entry : iface.addressEntries()) //遍历所有IP地址 { if (entry.ip().toString() selfip)//找到对应IP信息 { m_multicastIface iface; qDebug() 找到匹配网卡: iface.humanReadableName() IP: selfip; break; } } if (m_multicastIface.isValid()) break; } } //加入组播组 if (m_multicastIface.isValid()) { if (m_socket-joinMulticastGroup(groupAddress, m_multicastIface)) { qDebug() 通过网卡 m_multicastIface.humanReadableName() 加入组播组成功; // 设置组播发送的接口确保发送也走同一网卡 可不设置 udpsocket-setMulticastInterface(m_multicastIface); } else{ qWarning() 指定网卡加入组播组失败: udpsocket-errorString(); } }