跨大型和小型Endian机器的数据传输

时间:2013-05-24 07:11:36

标签: c char endianness

假设有3个字符串,如“cat”,“bat,”rat“。我需要将它们组合成一个字符串,并通过套接字编程将它们发送到另一台具有不同Endianess的计算机。

所以,如果另一台机器是大端,我将把字符串打包为:
memcpy (base, "cat", 3)
memcpy (base+3, "bat", 3)
memcpy (base+6, "rat", 3)

如果另一台机器是小端,我将把字符串打包为:
memcpy (base, "rat", 3)
memcpy (base+3, "bat", 3)
memcpy (base+6, "cat", 3)

我的方法是否正确?

其次,它们是否会以相反的顺序在另一台机器上实际收到?我的意思是当其他机器的软件开始从“基础”字符串中提取字符串时,它实际上是否会以相反的顺序 - 如鼠,棒,猫?

2 个答案:

答案 0 :(得分:5)

当将包含两个字节0x02 0x00的内存缓冲区转储到套接字中时,首先发送0x02,然后发送0x00。当接收器从套接字读取时,0x02将首先到达,并将存储在缓冲区的开头。 0x00到达第二位,并在0x02之后立即存储。因此,在您执行send(sock, &buffer, 2),接收者执行recv(sock, &buffer, 2)后,您和接收者的buffer的内容在字节级别上是相同的。

但是现在出现了解释问题。是的,你在内存中有两个字节0x02 0x00,但那又怎么样?他们的意思是什么?哦,它们是指0..65535范围内的整数,你说呢?但是有两种方法可以存储这样的数字。第一种是在第一个字节中存储更多有效位,因此512 = 10'00000000存储为0x02 0x00。第二个是在第一个字节中存储较低有效位,因此512存储为0x00 0x02,而0x02 0x00是存储2的方式,而不是512 }。

因此,重要的教训是:当您发送一些数据时,您必须确保接收器将像您一样解释它们。跨越多个字节的整数可以被不同地解释,因此您必须以某种方式就发送它们的方式达成协议。

现在,回到字符串。 C中的字符串是概念和表示级别的字节序列 - 整数不是这样!当你使用整数时,我敢打赌你并不在乎它们被表示为一堆字节,并且实际的表示不是由C指定的。你的编译器可以以任何你想要的方式存储整数。但是,字符串按特定顺序的字节序列,并且在C中固定。您有第一个字符,第二个字符,依此类推。因此,只有一种方法可以将02 00解释为字符串:它是一个包含第一个字符0x02的2个字符的字符串,第二个字符是0x00。不要混淆。

P.S。当然,当你开始认为字符串不是一个字节序列,而是一系列字符时,解释的问题又出现了:哪个字节意味着什么字符?但这是另一个故事。

编辑:在您对其他答案的评论中,您说“必须为其他计算机做出规定,以便知道我发送的内容实际上是整数而不是字符串”。是。这是与其他机器交换数据的主要问题:您发送的内容和他们看到的内容只是一个字节序列。现在,这个交换的所有参与者必须以相同的方式解释这个字节序列,否则他们会感到困惑。如果您要发送号码512并通过发送字节0x02 0x00来执行此操作,则另一方更好地了解0x02 0x00您的意思是512而不是2,或者,说START OF TEXT。或者,当您发送0x31 0x32 0x33 0x00时,您的意思是"123",而不是82537344031323300

仍然是原始问题的答案:“如果我发送"catbatrat",发件人会看到什么?”是:“发件人将看到"catbatrat",独立于字节序”。

答案 1 :(得分:3)

Endianness在字节级别上没有区别,因此您不需要担心8位字符的字符串或其他任何数据只是字节流的内容。

对于元素大于一个字节的任何内容,例如2个或更多字节整数,浮点等,然后你需要担心字节顺序,或者使用基于文本的格式进行数据交换。