QUdpSocket - дейтаграмма принимается дважды, почему?

Я дважды получаю дейтаграмму на своем QUdpSocket, хотя я смотрю на wireshark, и она получена только один раз. Я создаю сокет и слушаю порт 11112. Есть еще одно устройство, которое передает данные на этот порт, который я прослушиваю. Я постоянно получаю два сообщения для каждого фактического отправленного сообщения. Я не уверен, что вызывает это. есть идеи?

Урезанный код:

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_socket = new QUdpSocket(this);
          connect (m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
          m_socket->bind(11112, QUdpSocket::ShareAddress);
}

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

void MainWindow::readPendingDatagrams()
{
    QByteArray buffer;
    QHostAddress sender;
    quint16 port;

    while(m_socket->hasPendingDatagrams())
    {
        int s = m_socket->pendingDatagramSize();
        buffer.resize(s);
        //for some reason there are two datagrams on the line.
        // I have verified with wireshark that there is only one from the
        // sender so not sure what is happening under the hood...
        m_socket->readDatagram(buffer.data(),buffer.size(),&sender, &port);

        QString source = sender.toString().split(":")[3];
        if (source == "172.20.23.86")
        {
            qInfo() << buffer <<endl;
        }
    }


}

void MainWindow::onSocketStateChange(QAbstractSocket::SocketState state)
{
    if ( state == QAbstractSocket::BoundState ) {
           connect(m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
       }

}

person Carl Bartlett    schedule 01.11.2018    source источник


Ответы (2)


Это может произойти, если дейтаграмма отправлена ​​на широковещательный адрес, и вы привязаны ко всем интерфейсам (0.0.0.0), и есть два интерфейса, на которые принимается дейтаграмма. Чтобы исключить такую ​​возможность, переключитесь на receiveDatagram API и сбросьте все детали полученной дейтаграммы. Могу поспорить, что интерфейсы, на которых вы его получаете, каждый раз будут разными.

Вы также потенциально подключаете слот readPendingDatagrams несколько раз, и поэтому он может запускаться несколько раз, хотя hasPendingDatagrams должен возвращать false во второй раз, поэтому, хотя это может быть не проблема, это проблема, которую необходимо устранить. Он должен подключаться только один раз - при создании сокета, т.е. в конструкторе.

person Kuba hasn't forgotten Monica    schedule 01.11.2018
comment
Не могли бы вы пояснить, как я подключаю readPendingDatagrams несколько раз? - person Carl Bartlett; 01.11.2018
comment
Я изменил код, как было предложено, без изменения поведения - person Carl Bartlett; 01.11.2018
comment
@CarlBartlett Вы подключались несколько раз, потому что вы подключались каждый раз, когда сокет становился привязанным. Это может происходить несколько раз в течение жизни приложения, и в любом случае это ненужное усложнение: нет смысла подключаться к сигналу позже. - person Kuba hasn't forgotten Monica; 02.11.2018
comment
Я проверил с точками останова, сокет связывается только один раз, хотя в принципе я согласен, он не подключается несколько раз. - person Carl Bartlett; 02.11.2018
comment
Сокет может быть связан один раз, но он может быть связан с несколькими интерфейсами... - person Kuba hasn't forgotten Monica; 02.11.2018
comment
Передвинул для уверенности. Все те же результаты. - person Carl Bartlett; 02.11.2018

Unslander Моника правильная, привязывается ко всем интерфейсам по умолчанию, исправить можно m_socket-›bind(QHostAddress::LocalHost,11112);

person AlanZheng    schedule 22.12.2020