使用UDP协议和writeDatagram发送结构

时间:2014-06-11 07:24:38

标签: c++ qt sockets udp

我的目标是通过UDP协议发送一个结构,我的问题是我用来做它的函数与他的参数中的结构不兼容。 (我使用QT)

这是我制作的代码:

void MyUDP::sendUDP()
{
    typedef struct MyStructTag
    {
       int test1;
       bool test2;
       char test3;
    } MyStruct;

    MyStruct envoie;

    // Sends the datagram datagram
    // to the host address and at port.
    // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram,
    //                      const QHostAddress & host, quint16 port)

    socket->writeDatagram(envoie, QHostAddress("10.100.14.79"), 4000);


}

我知道这一行是完全错误的:socket->writeDatagram(envoie, QHostAddress("10.100.14.79"), 4000);但我不知道如何正确使用这个功能,或者是否有替代这个功能?

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

通过电线发送裸露的结构几乎总是错误,因为你无法保证它是如何打包的 - 成员之间是否存在填充,是什么?字节序,是否有任何你不知道的额外内部字段?如果接收者在同一平台上运行相同的二进制文件,则只能这样做。根据{{​​3}},运行相同的二进制文件本身是不够的。

正确的方法是使用QDataStream来序列化结构:

void MyUDP::sendUDP()
{
  struct MyStruct
  {
     int test1;
     bool test2;
     char test3;
  };
  MyStruct envoie;

  QByteArray buf;
  QDataStream s(&buf, QIODevice::WriteOnly);
  // The encoding is big endian by default, on all systems. You 
  // can change it if you wish.
  if (false) s.setByteOrder(QDataStream::LittleEndian);
  s << (qint32)envoie.test1 << (quint8)envoie.test2 << (qint8)test3;
  socket->writeDatagram(buf, QHostAddress("10.100.14.79"), 4000);
}

我在fat binaries中就同一主题提供了更多详细信息。

答案 1 :(得分:0)

快速搜索socket->writeDatagram()实际期望的内容(see docs)之后,似乎有两个带有此名称的重载函数。一个期望const char *和一个大小,另一个期望QByteArray引用。在这两种情况下,这意味着您需要将结构打包成这些格式,并将它们解压缩到另一端的结构中。因此,在const char *的情况下,创建一个适合您的结构的字符数组

unsigned int size=sizeof(int)+sizeof(bool)+sizeof(char)
char cBuffer[size];

并像这样包装

unsigned int nPos=0;
memcpy(cBuffer[nPos],envoie.test1,sizeof(int));
nPos+=sizeof(int);
memcpy(cBuffer[nPos],envoie.test2,sizeof(bool));
nPos+=sizeof(bool);
memcpy(cBuffer[nPos],envoie.test3,sizeof(char));

该功能的第二种形式可能有一些更好的方式来收拾东西,但我不熟悉Qt,所以你必须查看它是如何做到的,以及它是否比我上面给出的选项更好。根据我给出的选项,如果两台机器没有相同的字节顺序,它们也可以切换字节的顺序。这对整数类型最重要。长度为一个字符(即char)的类型不会成为问题,而且通常浮点数也不是问题(尽管不要引用我的话)。使用QtByteArray可能会更好一点,但快速浏览documentation上的{{3}}似乎并没有说明处理不同的字节序。处理不同字节序的一般方法是将事物转换为网络字节顺序或大端字节顺序。可能有一些函数可以将整数从本机字节序转换为网络字节顺序,并在另一端返回到本机字节序。