假设有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)
我的方法是否正确?
其次,它们是否会以相反的顺序在另一台机器上实际收到?我的意思是当其他机器的软件开始从“基础”字符串中提取字符串时,它实际上是否会以相反的顺序 - 如鼠,棒,猫?
答案 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"
,而不是825373440
或31323300
。
仍然是原始问题的答案:“如果我发送"catbatrat"
,发件人会看到什么?”是:“发件人将看到"catbatrat"
,独立于字节序”。
答案 1 :(得分:3)
Endianness在字节级别上没有区别,因此您不需要担心8位字符的字符串或其他任何数据只是字节流的内容。
对于元素大于一个字节的任何内容,例如2个或更多字节整数,浮点等,然后你需要担心字节顺序,或者使用基于文本的格式进行数据交换。