У меня есть проблемы, чтобы найти, почему мой короткий QUdpSocket
пример не работает. Я планирую использовать только один сокет UDP для чтения и записи во встроенное устройство по адресу 192.168.2.66 на порту 2007. Устройство будет всегда отвечать отправителю на порту 2007. Я протестировал устройство с программным обеспечением терминала UDP и работает как я сказал. Итак, я разработал простой класс для встраивания функций, необходимых для управления устройством:
class QUdp : public QObject
{
// Q_OBJECT
public:
explicit QUdp(QObject *parent = 0, const char *szHost = 0, uint16_t wPort = 0);
~QUdp();
bool Open();
int64_t Write(QByteArray &data);
int64_t Write(QString strData);
private:
QString m_strHost;
uint16_t m_wPort;
QUdpSocket *OUdp;
private slots:
void received();
};
Я полагаю, что проблема в методе Open:
bool QUdp::Open()
{
QHostAddress OHost;
connect(OUdp, &QUdpSocket::readyRead, this, &QUdp::received);
bool zRet = OUdp->bind(QHostAddress::AnyIPv4, m_wPort, QUdpSocket::ShareAddress);
OHost.setAddress(m_strHost);
OUdp->connectToHost(OHost, m_wPort, QIODevice::ReadWrite);
return(zRet);
}
//------------------------------------------------------------------------
Я использовал синтаксис Qt 5 для connect (), m_strHost
значение равно «192.168.2.66» и m_wPort
это 2007
Мой метод записи очень прост (часть внутри #if 0 была добавлена, чтобы увидеть, получил ли сокет какие-либо данные)
int64_t QUdp::Write(QString strData)
{
QByteArray data(strData.toStdString().c_str(), strData.length());
int64_t iCount = OUdp->write(data);
#if 0
bool zRecved = OUdp->waitForReadyRead(3000);
int64_t iRecvCount = OUdp->bytesAvailable();
#endif
return(iCount);
}
//------------------------------------------------------------------------
и это мой метод метода test () … Я написал его только для того, чтобы проверить, работает ли сигнальный слот или нет:
void QUdp::received()
{
int64_t iRecvCount = OUdp->bytesAvailable();
}
//------------------------------------------------------------------------
Я не понимаю, что не так .. Я нашел несколько сообщений, в которых говорится, что невозможно читать и писать, используя только один UDP-сокет в Qt (Qt использует BSD-сокеты, поэтому это должно быть возможно), но мой пример выглядит как предлагаемые решения, поэтому я действительно не понимаю, что не работает.
Вы можете читать и писать, используя только один сокет UDP в Qt. У меня это работает в Qt5 на Windows и Linux, так что не беспокойтесь там 🙂
Чтобы установить прямую связь Rx в QUdpSocket
Вы должны действительно использовать функцию bind (), что-то вроде этого:
// Rx connection: check we are not already bound
if (udpSocket->state() != udpSocket->BoundState)
{
// Rx not in bound state, attempt to bind
udpSocket->bind(address, port);
}
После этого вы сможете проверить, что udpSocket->state() == udpSocket->BoundState
Это правда, тогда вы успешно «привязаны» к этому IP / порту. Теперь ваше прослушивание может начаться, если ваше соединение с readready()
верно. Я не использовал этот синтаксис подключения, который вы используете, поэтому я не могу много говорить об этом, но вот пример того, как я подключаюсь:
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(rxDataEvent()), Qt::QueuedConnection);
Где «это» класс, который содержит мой QUdpSocket
а также udpSocket
это QUdpSocket
указатель. затем rxDataEvent
определяется ниже:
void CIpComms::rxDataEvent(void)
{
QByteArray rxData;
QHostAddress sender;
quint16 senderPort;
while (udpSocket->hasPendingDatagrams())
{
// Resize and zero byte buffer so we can make way for the new data.
rxData.fill(0, udpSocket->pendingDatagramSize());
// Read data from the UDP buffer.
udpSocket->readDatagram(rxData.data(),
rxData.size(),
&sender,
&senderPort);
// Emit ipDataReceived Signal
emit ipDataReceived(rxData);
}
}
Здесь мы постоянно проверяем датаграммы до тех пор, пока они не ожидают (немного проще, чем делать всю «bytesAvailable вещь») и вставляем данные в QByteArray
и испустить его в другом месте (что вам, очевидно, не нужно делать!).
Это все, что вам нужно сделать для подключения. Тогда отправить очень просто, нужно просто позвонить writeDatagram()
Ну, есть и другие варианты, но это гораздо проще в использовании:
if (-1 == udpSocket->writeDatagram(txData, address, port))
{
// Data write failed, print out warning
qWarning() << "Unable to write data to " << address.toString() << ":" << port << endl;
return false;
}
Я в значительной степени вырезал и вставил это из моего рабочего кода (с несколькими правками, чтобы он был кратким и простым, поэтому он должен дать вам отправную точку. Итак, я считаю, что вы идете не так, как будто вы не «на IP-адрес / порт и, следовательно, НЕ слушают его и не будут получать какие-либо readReady()
События.
Других решений пока нет …