0

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

为了解决基本问题,我有:

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

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

  • 尝试使用setReadBufferSize()和增加接收缓冲区大小setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, ...)

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

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

// 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
4

0 回答 0