Qt 客户端程序Udp通信和广播

一,UDP 通信流程

1,创建QUdpSocket

 QUdpSocket * udp_p = new QUdpSocket(this);

2,绑定端口并建立打开连接

        udp_p->bind(src_port);
        udp_p->open(QIODevice::OpenModeFlag::ReadWrite);

bind传入的端口为远程端口

3,建立信号连接

   connect(udp_p, &QUdpSocket::readyRead, this, &UdpComm::DoRecv);
    connect(udp_p, &QUdpSocket::disconnected, this, &UdpComm::DoOnDisconnected);
    connect(udp_p, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
                this, &UdpComm::DoError);

其中DoRecv DoOnDisconnected DoError 我们自己定义的槽函数,当收到数据或者断开连接或者发生错误会触发这三个函数的调用,我们可以在这几个函数处理我们的业务逻辑

4,发送数据

     QHostAddress addr(des_ip_);
        res = udp_p->writeDatagram(data, len, addr, des_port_);

5,接收数据

void UdpComm::DoRecv() {
    QByteArray *datagram;
    QHostAddress host;
    quint16 port = 0;

    if(udp_p == nullptr )
    {
        qDebug() << "DoRecv error udp_p is null" <<endl;
        return;
   }

    if( udp_p->isOpen() == false)
    {
        qDebug() << "DoRecv error udp_p is not open" <<endl;
        return;
   }

    datagram = new QByteArray();
    datagram->resize(static_cast<int>(udp_p->pendingDatagramSize()));

    qint64 res;
     res = udp_p->readDatagram(datagram->data(),datagram->size(), &host, &port);

    if (res < 0) {
        emit onError(ErrorRecv, QString::number(res));
    } else {
        QHostAddress ipv4(host.toIPv4Address());
        received_client_ip_ = ipv4.toString();
        received_client_port_ = port;
        emit onRecv(datagram, received_client_ip_, received_client_port_);
    }

    delete datagram;
}

void UdpComm::DoError(QAbstractSocket::SocketError se) {
    Q_UNUSED(se)
    QString error_str = "unknown error";
    if(udp_p != nullptr) {
        error_str = udp_p->errorString();
    }
    emit onError(ErrorConnection, error_str);
}

这个方法我们调用 readDatagram方法来接收数据,并且获取发送的IP和地址

二,UDP 广播流程

1,创建QUdpSocket

 QUdpSocket * udp_p = new QUdpSocket(this);

2,绑定端口


         if(!udp_p->bind(local_ip.isEmpty() ? QHostAddress::Any : QHostAddress(local_ip), des_port_))
         {
                   QString error = QString("Create socket failed! %1").arg(udp_p->errorString());
                   qDebug() << error <<endl;
                  udp_p->deleteLater();
          }
udp_p->open(QIODevice::OpenModeFlag::ReadWrite);udp_p->open(QIODevice::OpenModeFlag::ReadWrite);

绑定端口需要传入参数,第一个参数是本机设备的IP地址,第二个参数是目标地址的端口。

注意:这里第一个IP一定要填写本机的IP,由于电脑端可能会有多个iP的情况,例如虚拟IP 或者 WiFiIP之类的,对于某些IP,广播之后肯能不成功或者接收不到数据,所以可能需要用户在界面上选择本机IP并且进行多次尝试不同的本机IP进行广播。

下面是获取本机IP的方法

    //获取本机IP
   QList<QHostAddress>	hostAddressList = QNetworkInterface::allAddresses();
   foreach (QHostAddress address, hostAddressList)
   {
       if (!address.isLoopback() && !address.isMulticast()  && address.protocol() == QAbstractSocket::IPv4Protocol) {
          qDebug() << "本机IP " << address.toString() <<endl;
          ui->local_ip->addItem(address.toString());
       }

   }

我在这里获取到了本机IP之后加入了选择框可供用户选择,尝试发送广播 

3,建立信号连接

   connect(udp_p, &QUdpSocket::readyRead, this, &UdpComm::DoRecv);
    connect(udp_p, &QUdpSocket::disconnected, this, &UdpComm::DoOnDisconnected);
    connect(udp_p, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
                this, &UdpComm::DoError);

 4,发送数据

     QHostAddress addr(des_ip_);
        res = udp_p->writeDatagram(data, len, addr, des_port_);

注意这里发送的地址一般写死:255.255.255.255  端口就写你要广播的目标端口。当然如果你知道你要广播的地址属于哪个网段,你也可以广播到这个网段.例如:192.168.10.255

5,接收数据

void UdpComm::DoRecv() {
    QByteArray *datagram;
    QHostAddress host;
    quint16 port = 0;

    if(udp_p == nullptr )
    {
        qDebug() << "DoRecv error udp_p is null" <<endl;
        return;
   }

    if( udp_p->isOpen() == false)
    {
        qDebug() << "DoRecv error udp_p is not open" <<endl;
        return;
   }

    datagram = new QByteArray();
    datagram->resize(static_cast<int>(udp_p->pendingDatagramSize()));

    qint64 res;
     res = udp_p->readDatagram(datagram->data(),datagram->size(), &host, &port);

    if (res < 0) {
        emit onError(ErrorRecv, QString::number(res));
    } else {
        QHostAddress ipv4(host.toIPv4Address());
        received_client_ip_ = ipv4.toString();
        received_client_port_ = port;
        emit onRecv(datagram, received_client_ip_, received_client_port_);
    }

    delete datagram;
}

void UdpComm::DoError(QAbstractSocket::SocketError se) {
    Q_UNUSED(se)
    QString error_str = "unknown error";
    if(udp_p != nullptr) {
        error_str = udp_p->errorString();
    }
    emit onError(ErrorConnection, error_str);
}

三,区别

 通过上面可以看出正常UDP通信和发送广播有以下区别

1,广播的时候建立连接的时候需要绑定本机的IP,正常通信不需要

2,广播的时候发送给目标地址是固定的 ,一般是255.255.255.255

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值