【问题标题】:UDP packet loss differs on package sizeUDP 丢包因包大小而异
【发布时间】:2014-10-19 21:31:49
【问题描述】:

我有在 Qt 中测试 udp 套接字的应用程序。这真的很简单。一个套接字绑定到端口并侦听传入的包。其他套接字用于发送包。包裹中的第一个数字是发件人发送的包裹,后续数据仅用于测试。当接收方收到包裹时,它会显示接收/发送速率。您可以更改包大小和发送包的计时器超时。我在两个不同的路由器后面有两台电脑,我这样测试过:

将两个套接字绑定到同一个端口。将端口转发添加到此端口。然后将数据包发送到 127.0.0.1 和路由器外部 ip。

两台电脑都显示,收到的最大包裹大小为 32kb - 28b。 28b 是 UDP 报头大小。我想。

然后我尝试在两台计算机之间以相同的方式进行测试。并且测试以一种方式显示相同的结果(例如,当我从 comp1 发送到 comp2 时),但是当我从 comp2 发送到 comp1 时,最大大小约为 3kb(2975b)。 Comp1 不会得到比这更大的包。

这是程序代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    receiveSocket(),
    sendSocket(),
    timer(),
    packetSend(0),
    packetReceived(0),
    address(),
    sendPort(63465), 
    receivePort(62345),
{
    ui->setupUi(this);

    timer.setSingleShot(false);
    timer.setInterval(100);

    receiveSocket.bind(receivePort);

    connect(&timer, SIGNAL(timeout()), this, SLOT(sendData()));
    connect(&receiveSocket, SIGNAL(readyRead()), this, SLOT(receiveData()));

    connect(ui->startButton, SIGNAL(clicked()), this, SLOT(startStopSend()));
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::receiveData()
{
    unsigned int otherSideSent = 0;
    do
    {
        receiveDatagram.resize(receiveSocket.pendingDatagramSize());
        receiveSocket.readDatagram(receiveDatagram.data(), receiveDatagram.size());
    }while(receiveSocket.hasPendingDatagrams());

    QDataStream in(&receiveDatagram, QIODevice::ReadOnly);
    in >> otherSideSent;

    float tempVal;
    std::vector<float> value;
    for (int i=0; i<receiveDatagram.size()/8 - 1;i++ )
    {
        in >> tempVal;
        value.push_back(tempVal);
    }

    packetReceived++;

    ui->packetData->setText(QString("I receive/you sent:     ")+QString::number(packetReceived)+QString("/")+QString::number(otherSideSent));
}


void MainWindow::sendData()
{
    QDataStream out(&sendDatagram, QIODevice::WriteOnly);
    out << ++packetSend;
    for(unsigned int i = 0; i < 8185; ++i)
    {
        out << 1.0 + i/100.0;
    }

    sendSocket.writeDatagram(sendDatagram, address, sendPort);
}


void MainWindow::startStopSend()
{
    if(!timer.isActive())
    {
        address.setAddress(ui->ipLine->text());
        timer.start();
    }
    else
    {
        timer.stop();
    }
}

我认为,第一次测试表明没有 router1、router2、comp1 或 comp2 限制 UDP 包的最大大小。但仅在从 comp2 到 comp1 的情况下,最大包大小被限制为奇数。

问题是为什么?

【问题讨论】:

  • 问题是……? UDP 丢失数据包的方式、时间和原因介于实现相关和随机之间。
  • 我认为,第一次测试表明没有 router1、router2、comp1 或 comp2 限制 UDP 包的最大大小。但仅在从 comp2 到 comp1 的情况下,最大包大小被限制为奇数。为什么?
  • 将数据包分成片段比重新组合它们更容易(并且需要更少的内存)。

标签: c++ qt sockets networking


【解决方案1】:

大多数设备支持最大约 1500 字节的 MTU/MRU。您可以发送/接收比这更大的数据包这一事实意味着您要么一直启用巨型帧,要么数据包变得碎片化。

不是 100% 清楚你在做什么,但你提到了router external IP。如果两台计算机位于通过两个不同路由器连接到 Internet 的两个不同位置,那么您发送的超大数据包肯定会被“连接 Internet”的路由器分段。

我真的认为你可以通过互联网从comp1comp2 发送 32KB 数据包,如果你真的这样做的话,因为路由器必须首先分段它不会太高兴它接收到一个 32KB 大小的数据包,并且必须将其分割成 32 x 1KB 的数据包,更不用说接收端,它必须重新组装它。

当您说“测试 udp 套接字”时,我不确定您要测试的究竟是什么,但出于这个原因,大多数网络测试都是使用小于 1518(或 1522)字节的数据包大小执行的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多