什么是在C中转换字符串顺序的可移植方式

我正在尝试编写可与任何可以建立套接字连接的标准客户端进行通信的服务器(例如telnet客户端)

它最初是一个echo服务器,当然不需要担心网络字节排序。

我熟悉ntohs,ntohl,htons,htonl函数。 如果我转移16位或32位整数,或者如果发送的字符串中的字符是2或4字节的倍数,那么它们本身就会很好。

我想创建一个对字符串进行操作的函数,例如:

str_ntoh(char* net_str, char* host_str, int len) { uint32_t* netp, hostp; netp = (uint32_t*)&net_str; for(i=0; i < len/4; i++){ hostp[i] = ntoh(netp[i]); } } 

或类似的东西。 上面的假设是单词大小为32位。 我们不能确定发送机器上的字数不是16位还是64位正确?

对于客户端程序,例如telnet,他们必须在发送之前使用hton *,在接收数据之后使用ntoh *,对吗?

编辑:对于那些人而言,因为1-char是一个字节,字节序无关紧要:

 int main(void) { uint32_t a = 0x01020304; char* c = (char*)&a; printf("%x %x %x %x\n", c[0], c[1], c[2], c[3]); } 

运行此代码段。 我的输出如下:

 $ ./a.out 4 3 2 1 

那些关于powerPC芯片组的人应该得到’1 2 3 4’但我们这些关于intel芯片组的人应该看看我上面得到的东西。

也许我在这里遗漏了一些东西,但是你在发送字符串,即字符序列? 那你就不用担心字节顺序了。 这仅适用于整数中的位模式。 字符串中的字符始终采用“正确”的顺序。

编辑:

Derrick,为了解决您的代码示例,我在Intel i7(little-endian)和旧的Sun Sparc(big-endian)上运行了以下(稍微扩展)的程序版本

 #include  #include  int main(void) { uint32_t a = 0x01020304; char* c = (char*)&a; char d[] = { 1, 2, 3, 4 }; printf("The integer: %x %x %x %x\n", c[0], c[1], c[2], c[3]); printf("The string: %x %x %x %x\n", d[0], d[1], d[2], d[3]); return 0; } 

正如您所看到的,我已经为您打印出一个整数添加了一个真正的char数组。

小端英特尔i7的输出:

 The integer: 4 3 2 1 The string: 1 2 3 4 

而big-endian Sun的输出:

 The integer: 1 2 3 4 The string: 1 2 3 4 

您的多字节整数确实以不同的字节顺序存储在两台机器上,但char数组中的字符具有相同的顺序。

将您的函数签名发布后,您不必担心字节顺序。 它接受一个只能处理8位字符的char *。 每个字符只有一个字节,就不会出现字节顺序问题。

如果您以UTF16或UTF32编码发送Unicode,则只会遇到字节顺序问题。 并且发送机器的端点与接收机器的端点不匹配。 对此的简单解决方案是使用UTF8编码。 大多数文本都是通过网络发送的。 面向字节,它也没有字节顺序问题。 或者您可以发送BOM。

如果您希望将它们作为8位编码发送(事实上您使用char意味着这就是您想要的),则无需进行字节交换。 但是,对于非ASCII字符的无关问题,所以同一字符> 127在连接的两端显示相同,我建议你发送类似UTF-8的数据,它可以代表所有的unicode字符并且可以安全地视为ASCII字符串。 基于默认编码获取UTF-8文本的方式因您使用的平台和库集而异。

如果您要发送16位或32位编码…您可以包含一个带字节顺序标记的字符,另一端可以使用该字符来确定字符的字节顺序。 或者,您可以假设网络字节顺序并按照建议使用htons()htonl() 。 但是如果您想使用char ,请参阅上一段。 🙂

在我看来,函数原型与其行为不匹配。 你传递了一个char *,但是你将它转换为uint32_t *。 而且,仔细观察,你是在投射指针的地址,而不是内容,所以我担心你会得到意想不到的结果。 也许以下方法会更好:

 arr_ntoh(uint32_t* netp, uint32_t* hostp, int len) { for(i=0; i < len; i++) hostp[i] = ntoh(netp[i]); } 

我的假设是你真正得到的是一个uint32_t数组,你想在所有这些数组上运行ntoh()。

我希望这是有帮助的。