编码,将整数解码为char数组

时间:2009-11-09 14:38:59

标签: c network-programming

请注意,这不是作业,我在开始这个新主题之前进行了搜索。我得到了Store an int in a char array?

我正在寻找答案但在上述帖子中没有得到任何满意的答案。

这是我的要求:我想在一个字节数组中编码我的数据(比如整数),然后通过网络传输,然后在另一端解码并处理它。

这是编码部分:

const int MAX=5;
uint32_t a = 0xff00ffaa;
char byte_array[1024]; // this is the array to be transferred over the network
char buff[MAX]="";
sprintf(buff,"%4d",a);
memcpy(byte_array,buff,4);
// fill remaining stuff in the byte array and send it over the network

这是解码部分:

const int MAX=5;
char buff[MAX]="";
strncat(buff,byte_array,4)

int i=atoi(buff);
// Work with i

以下是我的问题:

1)以上代码是否可移植?我猜是(请纠正我)

2)现在,我希望用3个字节(但整数大小为4)对字节数组进行编码,即假设整数存储0x00ffaabb,我只希望字节数组在第1个索引中具有ff int第0个索引aa bb在第二个指数中。怎么做?

snprinf似乎没有用,或者我可能错过了什么。

实施任何网络协议的人都可以轻松帮助我。 我想,解码逻辑仍然有用。 (strncat(buff,byte_array,3)后跟atoi函数调用。)

以下是协议所说的内容:

    --------+--------+--------+--------+------------------------------
    |Version|   3       byte    length |  Remaining stuff
    --------+--------+--------+--------+------------------------------

版本为1个字节,后跟3个字节的消息长度。

我希望我能澄清我的问题

10 个答案:

答案 0 :(得分:6)

您将以ASCII格式存储,您应该自己存储字节。

编码应该类似于:

uint32_t a = 0xff00ffaa;
unsigned char byte_array[1024];

注意我是如何使目标数组无符号的,以表明它是“原始字节”,而不是实际字符。

byte_array[0] = a >> 24;
byte_array[1] = a >> 16;
byte_array[2] = a >> 8;
byte_array[3] = a >> 0;

使用big-endian字节排序将变量a序列化为byte_array的前四个字节,这是许多网络协议的默认排序。

您可能还希望在此处看到我的答案:question 1577161

答案 1 :(得分:4)

1)由于你使用一系列字符进行传输,它有点工作,我会亲自使用二进制协议。如果你可以使用你的变量的4个字节,我会看看htonl / ntohl函数(它们几乎在每个unix和windows上,因为w2k),否则见下文

2)使用二进制协议,编码将是

uint32_t a = 0xff00ffaa;
char byte_array[1024]; // this is the array to be transferred over the network

// leave byte_array[0] for version byte
// leave the high order byte in a since you want only the 3 lowest
byte_array[1] = (char)((a & 0x00FF0000)>>16);
byte_array[2] = (char)((a & 0x0000FF00)>>8);
byte_array[3] = (char)(a & 0x000000FF);

并且解码将是

uint32_t a = 0;
a |= byte_array[1]<<16;
a |= byte_array[2]<<8;
a |= byte_array[3];

答案 2 :(得分:2)

你正在做的事情将是多种多样的工作。您没有传输数据的字节 - 您正在传输数据的数值。因此,对于您要发送的数据,大小为5的缓冲区太小(0xFF00FFAA的数值为4278255530 - 10个字节)。

要传输字节,您需要执行以下操作(假设小端):

编码:

char array[1024]; // outgoing network data
int next = 0;

array[next++] = value & 0xFF;
array[next++] = (value >> 8) & 0xFF;
array[next++] = (value >> 16) & 0xFF;
array[next++] = (value >> 24) & 0xFF;

这些语句剥离了值的字节,并将它们分配给数组中的连续值。

解码:

char array[1024]; // incoming network data
int next = 0;

value = 0;
value |= (int)*((unsigned char*)array)[next++];
value |= (int)*((unsigned char*)array)[next++] << 8;
value |= (int)*((unsigned char*)array)[next++] << 16;
value |= (int)*((unsigned char*)array)[next++] << 24;

这些语句将字节拉出数组并将它们推回到值中。

如果您想尝试优化网络格式而不是传输字节,则可以消除部分数据。但请记住,您的发送方和接收方需要彼此了解所期望的内容 - 因此需要对所传递的数据元素的类型或长度进行一些沟通。

答案 3 :(得分:1)

至少要是可移植的,你应该考虑编码时可能的不同字节顺序。

您真的需要实施新的网络消息传递协议吗? NASA IPC或Sun RPC不适合你吗?它们都足够稳定,NASA更容易启动,RPC似乎可以更广泛地使用(是的,它已经可以使用,库可用于大多数流行的系统)。

  • 对于RPC,请尝试'man rpc'
  • 对于NASA IPC外观here

答案 4 :(得分:1)

也许您需要使用现有协议来完成此工作,在这种情况下,请忽略我的答案。

为什么不使用谷歌的Protocol Buffers图书馆来完成这项工作呢?更简单,更灵活,更高效。

答案 5 :(得分:1)

使用XDRRFC 4506)。

答案 6 :(得分:0)

你拥有的东西不会以你拥有它的方式运作。例如,a是32位,在您的示例中,您设置了高位,这意味着它不能与printf语句匹配为4位数。 (0xff00ffaa = 4278255530,超过4位)我相信它会溢出缓冲区。我相信printf会转换它并溢出字段,但它取决于当没有足够的缓冲区空间时编译器/ C如何实现printf函数。

对于您拥有的printf语句,您传入的最大值对于4个字符将是9999。同样,在使用3字节长度字段传输数据的示例中,最大长度为999.理论上,如果长度加1,但声明的缓冲区为1024,则长度可能为1000。您需要的最大缓冲区长度为1004字节长。

使用ASCII字符确实可以使消息/数据在整个系统中可移植,但这是以使用更多带宽/空间和编程时间和精力来转换ASCII来传输数据为代价的。

看起来你有个好主意,但它还需要一些工作。

答案 7 :(得分:0)

最好使用一些现有的工具。如果你不能 - 你关心字节顺序(即这是一个跨平台协议吗?)

否则,你可以简单地做一些......

unsigned char msg[1024];
int writeIndex = 0;
[...]
int mynum  = 12345;
memcpy(msg + writeIndex , &mynum, sizeof mynum);
writeIndex += sizeof mynum;

并解码

//[...] also declare readIndex;
memcopy(&mynum, msg + readIndex, sizeof mynum);
readIndex += sizeof mynum;

(您可以使用unsigned char指针替换msg + index的概念,但这不太重要。)

使用像这样的memcpy可能会更慢,但也更具可读性。如果有必要,你可以在#define或inline函数中实现memcopy clone - 毕竟它只是一个简短的赋值循环。

答案 8 :(得分:0)

只有在您希望解码的字符串是由您自己的代码构建而且上面几行之外,才能使用atoi函数。即它只能用于类似草图的代码。

否则,特别是在您的情况下,当数据从网络到达时,atoi函数无法有意义地用于执行解码,因为它没有提供可用的错误处理机制,并且绝对没有溢出保护(未定义的行为)溢出)。唯一可以有意义地用于字符串到整数转换的函数是来自strto...组的函数,strtol

答案 9 :(得分:0)

我已经浏览了此页面一百万次,我非常感谢其他所有帮助我的答案。这是我正在使用的存根,与其他答案不同,因为它可以在for循环中使用:

undefined