2

私の短いQUdpSocket例が機能しない理由を見つけるのに問題があります。ポート 2007 で 192.168.2.66 にある組み込みデバイスの読み取りと書き込みに UDP ソケットを 1 つだけ使用する予定です。デバイスは常にポート 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);
}
//------------------------------------------------------------------------

connect() に Qt 5 構文を使用しました。m_strHost値は「192.168.2.66」で、m_wPort2007 です。

私の Write メソッドは非常に単純です ( #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);
}
//------------------------------------------------------------------------

そして、これは私のテスト receive() メソッドです...シグナルスロットが機能するかどうかを確認するためだけに書きました:

void QUdp::received()
{
    int64_t iRecvCount = OUdp->bytesAvailable();
}
//------------------------------------------------------------------------

何が悪いのかわかりません.. QtでUDPソケットを1つだけ使用して読み書きできないという投稿をいくつか見つけました(QtはBSDソケットを使用するため、可能であるはずです)が、私の例は提案された解決策のように見えるので、何が機能していないのか本当にわかりません。

4

1 に答える 1

2

Qt では、UDP ソケットを 1 つだけ使用して読み取りと書き込みを行うことができます。WindowsとLinuxの両方でQt5でこれを実行しているので、心配する必要はありません:)

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、それが true であることを確認できるようになり、この IP/ポートに正常に「バインド」されます。readready()への接続が正しければ、リスニングを開始できます。あなたが使用しているこの接続構文を使用していないため、それについてはあまり言えませんが、接続方法の例を次に示します。

connect(udpSocket, SIGNAL(readyRead()), this, SLOT(rxDataEvent()), Qt::QueuedConnection);

ここで、「this」は my を含むクラスでありQUdpSocketudpSocketポインター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」全体を実行するよりも少し簡単です)、データを a に貼り付けて、別の場所に出力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()イベントを受信しません。

于 2014-01-20T08:06:21.317 に答える