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()));
}
}
2 ответа
Это может произойти, если дейтаграмма отправляется на широковещательный адрес, и вы привязаны ко всем интерфейсам (0.0.0.0), и есть два интерфейса, на которые принимается дейтаграмма. Чтобы исключить эту возможность, переключитесь на receiveDatagram
API и дамп полной информации о дейтаграмме, которую вы получили. Держу пари, что интерфейсы, на которых вы его получаете, будут отличаться каждый раз.
Вы также подключаете readPendingDatagrams
слот потенциально несколько раз, и, следовательно, он может быть запущен несколько раз, хотя hasPendingDatagrams
должен вернуться false
во второй раз - так что, хотя это может и не быть проблемой, это проблема, которую вы должны решить. Он должен быть подключен только один раз - когда вы создаете сокет, т.е. в конструкторе.
Unslander Моника правильная, она привязывается ко всем интерфейсам по умолчанию, исправить можно m_socket->bind(QHostAddress::LocalHost,11112);