0


0

QtでUDP経由で符号なし文字としてデータを受信する方法はありますか?

UDP接続を使用してhttp://en.wikipedia.org/wiki/Qt_%28toolkit%29[Qt]アプリケーションに浮動小数点数を送信する必要があります。 Qtで利用できる機能は

qint64 readDatagram ( char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0 )

署名付き文字バッファーの形式でデータを受け入れます。 floatを文字列に変換して送信することはできますが、4バイトのfloatをより長いサイズの文字バッファーに変換するのは明らかに効率的ではありません。

私はこれらの2つの関数を手に入れて、4バイトの浮動小数点数を単一の32ビット整数に変換してネットワーク経由で転送しますが、これは単純なC ++ UDPプログラムでは正常に動作しますが、Qtではデータを符号なしcharとして受信する必要があります。

floatinfポイントデータを文字列に変換して送信することを避けることは可能ですか?

uint32_t htonf(float f)
{
    uint32_t p;
    uint32_t sign;

    if (f < 0) { sign = 1; f = -f; }
    else { sign = 0; }

    p = ((((uint32_t)f)&0x7fff)<<16) | (sign<<31); // Whole part and sign.
    p |= (uint32_t)(((f - (int)f) * 65536.0f))&0xffff; // Fraction.

    return p;
}

float ntohf(uint32_t p)
{
    float f = ((p>>16)&0x7fff); // Whole part.
    f += (p&0xffff) / 65536.0f; // Fraction.

    if (((p>>31)&0x1) == 0x1) { f = -f; } // Sign bit set.

    return f;
}

4 Answer


1


「readDatagram」を使用してみましたか? または、読み取り後にデータをhttp://doc.trolltech.com/4.6/qbytearray.html#QByteArray-3 [QByteArray]に変換しますか? 多くの場合、 char *`は実際には単なるバイト配列です。 これはそのような場合の1つです。 http://doc.trolltech.com/4.6/qudpsocket.html#writeDatagram-2 [`writeDatagram]はQByteArrayを取ることができることに注意してください。

一般に、ソケットを介して送信されるものはすべて文字列ではなくバイト単位であり、どちらの側の層も変換を行います。 http://doc.trolltech.com/4.6/qudpsocket.html#details [こちら]、特にBroadcasterの例をご覧ください。 ブロードキャストおよび受信用の「QByteArray」を作成する方法を示します。


0


質問は要件があいまいであるため、なぜダウン投票するのかわかりません。

4バイトのfloatは、1としてキャストされた場合、単純に4文字のバッファーです。 システムが同種の場合、フロートは符号付きchar *として送信でき、ビットごとに受信者の符号付きchar *に直接読み込まれ、変換は不要です。 システムが異種の場合、これは機能せず、とにかくポータブルな形式に変換する必要があります。 IEEE形式がよく使用されますが、私の質問は、どのような要件ですか、フロート形式はシステム間で同じですか?


0


私がそれを正しく読んだ場合、あなたの主な質問は、タイプ char`のバッファへのポインタを使用するQTの readDatagram`関数でタイプ `unsigned char`のデータを受信する方法です。

短い答えは、これらの線に沿ってキャストを使用することです:

const size_t MAXSIZE = 1024;
unsigned char* data = malloc(MAXSIZE);

readDatagram ( (unsigned char *)data, MAXSIZE, address, port )

同じIEEE浮動小数点形式を使用するマシンが複数あるが、一部はビッグエンディアン、一部はリトルエンディアンであると想定します。 https://stackoverflow.com/questions/1873352/how-do-i-convert-a-value-from-host-byte-order-to-little-endian [この問題に関する適切な議論については、このSO投稿を参照してください] 。

その場合、次のように少し簡単にすることができます。

const size_t FCOUNT = 256;
float* data = malloc(FCOUNT * sizeof(*data));

readDatagram ( (char *)data, FCOUNT * sizeof(*data), address, port )

for (int i = 0; i != FCOUNT; ++i)
    data[i] = ntohf(*((uint32_t*)&data[i]));

覚えておくべきことは、「readDatagram」などのネットワーク機能に関する限り、データは単なるビットの集まりであり、それらのビットがどのタイプとして解釈されるかは気にしないということです。


0


UDP接続の両端でQtを使用している場合、QDataStreamを確認することをお勧めします。 データグラムを読み取るたびにQByteArrayから作成し、必要な値(float、maps、list、QVariants、もちろん文字列)を読み取ることができます。

同様に、送信側でデータストリームを作成し、そこにデータをプッシュしてから、結果のQByteArrayをwriteDatagramで送信します。

明らかに、これは両端がQtを使用している場合にのみ機能します。データエンコーディングは明確に定義されていますが、手動で生成するのは簡単ではありません。

(ストリーム指向の動作が必要な場合は、QUDPSocketがデータストリームを持つQIODeviceであるという事実を使用できますが、データグラムごとの動作が必要なように聞こえます)