当前位置:   article > 正文

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

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

一,UDP 通信流程

1,创建QUdpSocket

 QUdpSocket * udp_p = new QUdpSocket(this);

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

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

bind传入的端口为远程端口

3,建立信号连接

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

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

4,发送数据

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

5,接收数据

  1. void UdpComm::DoRecv() {
  2. QByteArray *datagram;
  3. QHostAddress host;
  4. quint16 port = 0;
  5. if(udp_p == nullptr )
  6. {
  7. qDebug() << "DoRecv error udp_p is null" <<endl;
  8. return;
  9. }
  10. if( udp_p->isOpen() == false)
  11. {
  12. qDebug() << "DoRecv error udp_p is not open" <<endl;
  13. return;
  14. }
  15. datagram = new QByteArray();
  16. datagram->resize(static_cast<int>(udp_p->pendingDatagramSize()));
  17. qint64 res;
  18. res = udp_p->readDatagram(datagram->data(),datagram->size(), &host, &port);
  19. if (res < 0) {
  20. emit onError(ErrorRecv, QString::number(res));
  21. } else {
  22. QHostAddress ipv4(host.toIPv4Address());
  23. received_client_ip_ = ipv4.toString();
  24. received_client_port_ = port;
  25. emit onRecv(datagram, received_client_ip_, received_client_port_);
  26. }
  27. delete datagram;
  28. }
  29. void UdpComm::DoError(QAbstractSocket::SocketError se) {
  30. Q_UNUSED(se)
  31. QString error_str = "unknown error";
  32. if(udp_p != nullptr) {
  33. error_str = udp_p->errorString();
  34. }
  35. emit onError(ErrorConnection, error_str);
  36. }

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

二,UDP 广播流程

1,创建QUdpSocket

 QUdpSocket * udp_p = new QUdpSocket(this);

2,绑定端口

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

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

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

下面是获取本机IP的方法

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

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

3,建立信号连接

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

 4,发送数据

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

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

5,接收数据

  1. void UdpComm::DoRecv() {
  2. QByteArray *datagram;
  3. QHostAddress host;
  4. quint16 port = 0;
  5. if(udp_p == nullptr )
  6. {
  7. qDebug() << "DoRecv error udp_p is null" <<endl;
  8. return;
  9. }
  10. if( udp_p->isOpen() == false)
  11. {
  12. qDebug() << "DoRecv error udp_p is not open" <<endl;
  13. return;
  14. }
  15. datagram = new QByteArray();
  16. datagram->resize(static_cast<int>(udp_p->pendingDatagramSize()));
  17. qint64 res;
  18. res = udp_p->readDatagram(datagram->data(),datagram->size(), &host, &port);
  19. if (res < 0) {
  20. emit onError(ErrorRecv, QString::number(res));
  21. } else {
  22. QHostAddress ipv4(host.toIPv4Address());
  23. received_client_ip_ = ipv4.toString();
  24. received_client_port_ = port;
  25. emit onRecv(datagram, received_client_ip_, received_client_port_);
  26. }
  27. delete datagram;
  28. }
  29. void UdpComm::DoError(QAbstractSocket::SocketError se) {
  30. Q_UNUSED(se)
  31. QString error_str = "unknown error";
  32. if(udp_p != nullptr) {
  33. error_str = udp_p->errorString();
  34. }
  35. emit onError(ErrorConnection, error_str);
  36. }

三,区别

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/656480
推荐阅读
相关标签
  

闽ICP备14008679号