编码,整数进行解码,以字符数组

问题描述 投票:1回答:10

请注意,这不是功课,我也开始这一新的线程之前搜索。我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和我只是想将字节数组具有在第一索引FF INT第0索引AA和BB在第二个指标。怎么做?

snprinf似乎不工作或可能是我失去了一些东西。

谁已实施任何网络协议,可以很容易地帮助我的人。解码逻辑仍然会工作,我猜。 (strncat(buff,byte_array,3)接着atoi函数调用)。

这里的协议这样说:

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

版本是1个字节,然后该消息的3字节的长度。

我希望我能澄清我的问题

c network-programming
10个回答
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;

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

你也可以看到我的答案在这里:question 1577161


0
投票

我看了这个页面上百万次,我真的很感谢所有帮助我的答案。下面是我使用的存根,这是从其他的答案独一无二的,因为它可以被用在for循环:

void encode_int_as_char(int num, char *buf, int length){
    int i;
    for (i = 0; i < length; i++){
        buf[i] = (char)(num >> ((8 * (length - i - 1)) & 0xFF));
    }
}

int decode_int_from_char(char *enc, int length){
    int i, num, cur;

    num = 0;
    for (i = 0; i < length; i++){
        cur = (unsigned char) enc[i] << (8 * (length - i - 1));
        num += (int) cur;
    }

    return num;
}

4
投票

1)它有点工作,因为你使用的字符数组的运输,我会亲自使用二进制协议。如果你可以使用4个字节的变量,我会看看到htonl /功能再用ntohl(他们是在几乎所有的UNIX和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
投票

你在做什么会排序的工作。你不是传送数据的字节 - 你传送数据的数值。其结果是大小为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;

这些陈述拉出来的字节数组,并把它们放回入值。

如果您想尝试优化您的网络格式,而不是传输的字节就可以消除一些数据。但请记住,你的发送者和接收者需要互相知道会发生什么 - 所以需要有什么传递的数据元素的类型或长度是一些沟通。


1
投票

至少是便携式的,你应该考虑在编码可能不同的字节顺序。

你真的需要实现新的网络消息传输协议?不要NASA IPC或Sun RPC适合你?他们都是足够稳定,NASA是简单的启动,RPC似乎提供更广泛的(是的,它已准备好使用,库可用于最流行的系统)。

  • 对于RPC尝试“人RPC”
  • 对于NASA IPC看here

1
投票

也许你需要使这项工作与现有的协议,在这种情况下,忽略我的答案。

而不是在这里重新发明轮子,你为什么不使用谷歌的Protocol Buffers图书馆做这个工作?更简单,更灵活,效率非常高。


1
投票

使用XDRRFC 4506)。


0
投票

你有什么不会在你拥有了它的方式工作。例如,一个是32位,并在你的榜样,你的高阶位设置,这意味着它不适合与你的printf语句一个4位数字。 (0xff00ffaa = 4278255530,这是更然后4位)相信会溢出缓冲器中。我相信的printf会把它转换成溢流领域,但它取决于你的编译器/ C如何实现printf函数时没有足够的缓冲空间。

对于你有printf语句,你可以传递的最大值是9999 4个字符。同样,在你的数据与3字节长度字段转移的例子,你将有999理论上的最大长度的长度可能是1000,如果你加入基于长度,但你已经宣布的缓冲区,为1024在这里你需要的最大缓冲区长度是1004个字节长。

使用ASCII字符确实使整个系统信息/数据便携,但它是在使用更多的带宽/空间和编程的时间和精力来回转换,从ASCII传输数据的费用。

这似乎是你有一个好主意,但它仍然需要一些工作。


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;

(你可以用一个无符号的字符指针取代msg + index的概念,虽然这是不太可能的事情)。

使用的memcpy这样容易比较慢,但是也更易读。如果有必要,你可以实现在的#define或内联函数的存储器复制克隆 - 它只是分配一个短环,毕竟。


0
投票

使用atoi功能只有合理时,你是期待解码字符串是通过自己的代码生成和最多不超过一对夫妇以上线。即,只有在草图状代码可用。

否则,尤其是在你的情况下,当数据从网络到达时,atoi功能不能用于有意义进行解码,因为它没有提供可用的错误处理机制,并从溢完全没有保护(在发生溢出未定义行为)。可meanigfully用于字符串到整数转换的唯一功能是从strto...基,strtol你的情况的功能。

© www.soinside.com 2019 - 2024. All rights reserved.