什么是转换字节的便携方式
我试图编写服务器,将与任何可以进行套接字连接的标准客户端通信(例如,telnet客户端)
它起初是一个回声服务器,当然这并不需要担心网络字节排序。
我熟悉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 *,在收到数据后必须使用hnt *,正确的?
编辑:对于那些事情,因为1-char是一个字节,endian-ness无所谓:
int main(void)
{
uint32_t a = 0x01020304;
char* c = (char*)&a;
printf("%x %x %x %xn", c[0], c[1], c[2], c[3]);
}
运行这段代码。 我的输出如下:
$ ./a.out
4 3 2 1
那些在powerPC芯片组上应该得到'1 2 3 4',但我们intel芯片组上的人应该看到我大部分上面得到的东西。
也许我在这里错过了一些东西,但是你会发送字符串,也就是字符序列吗? 那么你不需要担心字节顺序。 这只适用于整数中的位模式。 字符串中的字符总是处于“正确”的顺序。
编辑:
Derrick,为了解决你的代码示例,我在Intel i7(小端)和旧的Sun Sparc(大端)上运行了以下(稍微扩展)的程序版本,
#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint32_t a = 0x01020304;
char* c = (char*)&a;
char d[] = { 1, 2, 3, 4 };
printf("The integer: %x %x %x %xn", c[0], c[1], c[2], c[3]);
printf("The string: %x %x %x %xn", d[0], d[1], d[2], d[3]);
return 0;
}
正如你所看到的,我已经添加了一个真正的字符数组到你的整数打印输出。
小端英特尔i7的输出:
The integer: 4 3 2 1
The string: 1 2 3 4
而大前锋Sun的输出:
The integer: 1 2 3 4
The string: 1 2 3 4
您的多字节整数的确在两台机器上以不同的字节顺序存储,但char数组中的字符具有相同的顺序。
通过发布的函数签名,您不必担心字节顺序。 它接受一个char *,它只能处理8位字符。 每个字符一个字节,不能有字节顺序问题。
如果您使用UTF16或UTF32编码发送Unicode,则只会遇到字节顺序问题。 并且发送机的序列号与接收机的序列号不匹配。 简单的解决方案是使用UTF8编码。 这是大多数文本在网络中发送的内容。 面向字节,它也没有字节顺序问题。 或者您可以发送物料清单。
如果您想将它们作为8位编码发送(您使用char
的事实意味着这是您想要的),则不需要字节交换。 但是,对于非ASCII字符的无关问题,以便在连接的两端显示相同的字符> 127
,我建议您以UTF-8的形式发送数据,这些数据可以表示所有的Unicode字符并可以安全地视为ASCII字符串。 根据默认编码获取UTF-8文本的方式因您使用的平台和库集而异。
如果您发送的是16位或32位编码......您可以包含一个带有字节顺序标记的字符,另一端可以用来确定字符的字节顺序。 或者,您可以假设网络字节顺序,并按照您的建议使用htons()
或htonl()
。 但是如果你想使用char
,请看前一段。 :-)