繁体   English   中英

如何将无符号char数组解析为数值数据

[英]how to parse unsigned char array to numerical data

我的问题的设置如下:

  • 我有一个将UDP数据包发送到接收计算机的源
  • 接收计算机接收UDP数据包,并将其接收到unsigned char *message

我可以使用以下方式按字节打印数据包

for(int i = 0; i < sizeof(message); i++) {
    printf("0x%02 \n", message[i];
}

这就是我的位置! 现在,我想开始将我收到的这些字节解析为短,整数,长和字符串。

我编写了一系列函数,例如:

short unsignedShortToInt(char[] c) {
    short i = 0;
    i |= c[1] & 0xff;
    i <<= 8;
    i |= c[0] & 0xff;
   return i;
}

解析字节并将其转换为int,long和short。 我可以使用sprintf()从字节数组创建字符串。

我的问题是-从大量UDP数据包中获取子字符串的最佳方法是什么? 该数据包的长度超过100个字符,因此我想一种简单的方法将message[0:6]message[20:22]传递给这些message[20:22] Utility函数。

可能的选择:

  • 我可以使用strcpy()为每个函数调用创建一个临时数组,但这似乎有些混乱。

  • 我可以将整个数据包转换为字符串,然后使用std::string::substr 这看起来不错,但是我担心将未签名的字符转换为已签名的字符(字符串转换过程的一部分)可能会导致一些错误(也许这种担心是不必要的吗?)。

  • 也许是另一种方式?

因此,我请stackoverflow推荐一种简洁的方法来完成此任务!

谢谢!

为什么不使用适当的 序列化

MsgPack

您将需要一个方案来区分消息。 例如,您可以使它们自我描述 ,例如:

struct my_message {
  string protocol;
  string data;
};

并根据协议调度解码。

使用经过测试的序列化库,可能比发现您的系统容易受到缓冲区溢出攻击和故障的影响更好。

我认为您有两个问题需要解决。 首先,从字符缓冲区提取整数数据后,需要确保整数数据在内存中正确对齐。 接下来,您需要确保整数数据在提取后正确的字节顺序。

对齐问题可以通过包含叠加在正确大小的字符数组上的整数数据类型的union来解决。 可以使用标准的ntohs()ntohl()函数解决网络字节顺序问题。 仅当发送软件还使用这些功能的逆序产生的标准字节顺序时,此方法才有效。

参见: http : //www.beej.us/guide/bgnet/output/html/multipage/htonsman.html

这是一些未测试的功能,您可能会发现它们有用。 我认为他们应该按照自己的意愿去做。

#include <netinet/in.h>

/**
 * General routing to extract aligned integral types
 * from the UDP packet.
 *
 * @param data Pointer into the UDP packet data
 * @param type Integral type to extract
 *
 * @return data pointer advanced to next position after extracted integral.
 */
template<typename Type>
unsigned char const* extract(unsigned char const* data, Type& type)
{
    // This union will ensure the integral data type is correctly aligned
    union tx_t
    {
        unsigned char cdata[sizeof(Type)];
        Type tdata;
    } tx;

    for(size_t i(0); i < sizeof(Type); ++i)
        tx.cdata[i] = data[i];

    type = tx.tdata;

    return data + sizeof(Type);
}

/**
 * If strings are null terminated in the buffer then this could be used to extract them.
 *
 * @param data Pointer into the UDP packet data
 * @param s std::string type to extract
 *
 * @return data pointer advanced to next position after extracted std::string.
 */
unsigned char const* extract(unsigned char const* data, std::string& s)
{
    s.assign((char const*)data, std::strlen((char const*)data));
    return data + s.size();
}

/**
 *  Function to parse entire UDP packet
 *
 * @param data The entire UDP packet data
 */
void read_data(unsigned char const* const data)
{
    uint16_t i1;
    std::string s1;
    uint32_t i2;
    std::string s2;

    unsigned char const* p = data;

    p = extract(p, i1); // p contains next position to read
    i1 = ntohs(i1);

    p = extract(p, s1);

    p = extract(p, i2);
    i2 = ntohl(i2);

    p = extract(p, s2);
}

希望能有所帮助。

编辑:

我已经编辑了包含字符串的示例。 这很大程度上取决于字符串在流中的存储方式。 本示例假定字符串是以N结尾的c字符串。

EDIT2:

糟糕,更改了代码以接受每个问题的未签名字符。

如果数组的长度只有100个字符,则只需创建一个char buffer[100]和一个queue ,这样您就不会错过任何消息的处理。

接下来,您可以按照描述的那样对缓冲区进行索引,如果您知道消息的结构,则可以知道索引点。

接下来,您可以union类型,即

union myType{
    char buf[4];
    int x;
 }

如果那是您需要的,则从char给出int的值

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM