QUdpSocket 有时会丢失数据报

问题描述

我正在尝试解决 Linux 上 Qt6 的网络错误,其中 QUdpSocket 没有接收到它应该接收的所有数据。虽然对于少量数据(以 kB 为单位),所有字节都会通过,但较大的数据报(~384 kB)从末尾被剪掉。在这种情况下,我测得在数据流的末尾丢失了大约 4kB。

为了解决基本问题,我有

  • 尝试将物理以太网连接从本地路由器更改为具有静态 IP 的点对点链接

  • 与 Wireshark 确认所有数据(包括剪辑位)都进入我的 Linux 套接字。并通过日志消息确认并非所有数据都从 QUdpSocket 中读出。

  • 尝试使用 setReadBufferSize()setSocketoption(QAbstractSocket::ReceiveBufferSizeSocketoption,...)

    增加接收缓冲区大小
  • 已验证当我使用 QNetworkDatagram 而不是缓冲区以及当我使用 QUdpSocket 的信号而不是同步接收模式时会出现相同的错误

这是我展示错误的最小示例代码

// Configuration constants:
static constexpr int TIMEOUT_MS = 250;
static constexpr int LOCAL_PORT = 1234;
static constexpr qsizetype READ_BUFFER_SIZE = 8388608; // bytes,more than enough for "small" as well as "large" data bursts

// Open a socket
auto socket = new QUdpSocket();
socket->bind(LOCAL_PORT);
if (socket->state() != QAbstractSocket::BoundState) {
  qDebug() << "Timeout!";
  return;
}

socket->setReadBufferSize(READ_BUFFER_SIZE); // according to Qt docs,this has no effect for QUdpSocket
socket->setSocketoption(QAbstractSocket::ReceiveBufferSizeSocketoption,READ_BUFFER_SIZE);

// Synchronously read from the socket
std::vector<char> data_buffer{};
forever {
  if (!socket->hasPendingDatagrams()) {
    waitForReadyRead(TIMEOUT_MS);
  }
  
  if (!socket->hasPendingDatagrams()) {
    qDebug() << "Timeout!";
    continue;
  }
  
  const qint64 recv_size = socket->pendingDatagramSize();
  data_buffer.resize(recv_size);
  
  const qint64 n_received{socket->readDatagram(data_buffer.data(),data_buffer.size())};
  if (n_received < 0) {
    qDebug() << "Error:" << socket->error();
    continue;
  } else if (n_received != recv_size) {
    qDebug() << "Error: received != ready size," << n_received << "!=" << recv_size;
    continue;
  }

  // This function just prints binary data in hex:
  printData(data_buffer.data(),data_buffer.size());
}

socket->close(); // never reached

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)