有没有办法在 Qt 上通过 UDP 接收无符号字符数据?
我需要使用 UDP 连接发送浮点数到 Qt 应用程序。现在,Qt 中唯一可用的函数是
qint64 readDatagram ( char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0 )
接受有符号字符缓冲区形式的数据。我可以将浮点数转换为字符串并发送它,但将 4 字节浮点数转换为更长的字符缓冲区显然效率不高。
我掌握了这两个函数,将 4 字节浮点数转换为无符号 32 位整数,以便通过网络传输,这对于简单的 C++ UDP 程序来说效果很好,但对于 Qt,我需要以无符号字符形式接收数据。
是否可以避免将浮点数数据转换为字符串然后发送?
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;
}
I need to send floating point numbers using a UDP connection to a Qt application. Now in Qt the only function available is
qint64 readDatagram ( char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0 )
which accepts data in the form of signed character buffer. I can convert my float into a string and send it but it will obviously not be very efficient converting a 4 byte float into a much longer sized character buffer.
I got hold of these 2 functions to convert a 4 byte float into an unsinged 32 bit integer to transfer over network which works fine for a simple C++ UDP program but for Qt I need to receive the data as unsigned char.
Is it possible to avoid converting the floatinf point data into a string and then sending it?
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您是否尝试过使用
readDatagram
?或者将数据转换为QByteArray
读完后?在许多情况下,char*
实际上只是一个字节数组。这是其中之一。请注意,writeDatagram
可以采用QByteArray。一般来说,通过套接字发送的所有内容都是字节而不是字符串,两端的层都会进行转换。请查看此处,尤其是广播公司示例。它们展示了如何创建用于广播和接收的
QByteArray
。Have you tried using
readDatagram
? Or converting the data to aQByteArray
after reading? In many cases achar*
is really just a byte array. This is one of those cases. Note that thewriteDatagram
can take a QByteArray.Generally every thing sent across sockets is in bytes not strings, layers on either end do the conversions. Take a look here, especially the Broadcaster examples. They show how to create a
QByteArray
for broadcast and receive.不知道为什么要投反对票,因为这个问题的要求很模糊。
如果转换为 1,4 字节浮点数只是一个 4 字符缓冲区。如果系统是同质的,则浮点数可以作为有符号的 char * 发送,并且逐位读取到接收器上的有符号 char * 中将是相同的,无需转换。如果系统是异构的,那么这将不起作用,无论如何您都需要将其转换为可移植格式。经常使用IEEE格式,但我的问题仍然是,有什么要求,系统之间的浮点格式是否相同?
Not sure why the downvote, since the question is vague in requirements.
A 4-byte float is simply a 4 character buffer, if cast as one. If the systems are homogenous, the float can be sent as a signed char *, and bit for bit it'll be the same read into the signed char * on the receiver directly, no conversion needed. If the systems are heterogenous, then this won't work and you need to convert it to a portable format, anyway. IEEE format is often used, but my question is still, what are the requirements, is the float format the same between systems?
如果我没读错的话,您的主要问题似乎是如何使用 QT 的 readDatagram 函数接收
unsigned char
类型的数据,该函数使用指向类型缓冲区的指针字符
。简短的答案是使用以下类型的强制转换:
我假设您有多台机器,它们使用相同的 IEEE 浮点格式,但其中一些是大端,一些是小端。 请参阅此帖子了解这个问题的讨论很好。
在这种情况下,您可以做一些更简单的事情,如下所示:
要记住的是,就像 readDatagram 这样的网络功能而言,数据只是一堆位,它并不关心这些位被解释为什么类型。
If I read it correctly, your primary question seems to be how to receive data of type
unsigned char
with QT'sreadDatagram
function which uses a pointer to a buffer of typechar
.The short answer is use a cast along these lines:
I'm going to assume you have multiple machines which use the same IEEE floating point format but some of which are big endian and some of which are little endian. See this SO post for a good discussion of this issue.
In that case you could do something a bit simpler like this:
The thing to remember is that as far as networking functions like
readDatagram
are concerned, the data is just a bunch of bits and it doesn't care what type those bits are interpreted as.如果 UDP 连接的两端都使用 Qt,我建议查看 QDataStream。每次读取数据报时,您都可以从 QByteArray 创建它,然后读取您需要的任何值 - 浮点数、映射、列表、QVariants,当然还有字符串。
类似地,在发送端,您将创建一个数据流,将数据推送到其中,然后通过 writeDatagram 发送生成的 QByteArray。
显然,只有当两端都使用 Qt 时,这才有效 - 数据编码是明确定义的,但手动生成并不简单。
(如果您想要面向流的行为,您可以使用 QUDPSocket 是具有数据流的 QIODevice 的事实,但这听起来好像您想要每个数据报的行为)
If both ends of your UDP connection use Qt, I would suggest looking at QDataStream. You can create this from a QByteArray each time you read a datagram, and then read whatever values you require - floats, maps, lists, QVariants, and of course string.
Similarly, on the sending side, you'd create a data stream, push data into it, then send the resulting QByteArray over writeDatagram.
Obviously this only works if both ends use Qt - the data encoding is well-defined, but non-trivial to generate by hand.
(If you want stream orientated behaviour, you could use the fact that QUDPSocket is a QIODevice with a data-stream, but it sounds as if you want per-datagram behaviour)