oar*_*ish 9 c sockets networking endianness
我正在尝试使用unix套接字来测试向localhost发送一些udp数据包.
我的理解是,当设置IP地址和端口以便发送数据包时,我会将我sockaddr_in的值转换为网络字节顺序.我在OSX上,我对此感到惊讶
printf("ntohl: %d\n", ntohl(4711));
printf("htonl: %d\n", htonl(4711));
printf("plain: %d\n", 4711);
Run Code Online (Sandbox Code Playgroud)
打印
ntohl: 1729232896
htonl: 1729232896
plain: 4711
Run Code Online (Sandbox Code Playgroud)
所以这两个函数都没有实际返回普通值.我本来期望看到任何结果不同,因为86是小端(据我所知),或者是相同的,同为实际数量4711显然,我不明白是什么htonl和ntohl及其变种做.我错过了什么?
相关代码是这样的:
int main(int argc, char *argv[])
{
if (argc != 4)
{
fprintf(stderr, "%s\n", HELP);
exit(-1);
}
in_addr_t rec_addr = inet_addr(argv[1]); // first arg is '127.0.0.1'
in_port_t rec_port = atoi(argv[2]); // second arg is port number
printf("Address is %s\nPort is %d\n", argv[1], rec_port);
char* inpath = argv[3];
char* file_buf;
unsigned long file_size = readFile(inpath, &file_buf); // I am trying to send a file
if (file_size > 0)
{
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = rec_addr; // here I would use htons
dest.sin_port = rec_port;
printf("ntohs: %d\n", ntohl(4711));
printf("htons: %d\n", htonl(4711));
printf("plain: %d\n", 4711);
int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (socket_fd != -1)
{
int error;
error = sendto(socket_fd, file_buf, file_size + 1, 0, (struct sockaddr*)&dest, sizeof(dest));
if (error == -1)
fprintf(stderr, "%s\n", strerror(errno));
else printf("Sent %d bytes.\n", error);
}
}
free(file_buf);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如其他人所说,无论是htons和ntohs扭转little-endian的机器上的字节顺序,并在大端机器空操作.
没有提到的是这些函数采用16位值并返回16位值.如果要转换32位值,则需要使用htonl而ntohl不是.
这些函数的名称来自某些数据类型的传统大小.的s代表short,而l代表long.A short通常为16位,而较旧的系统long为32位.
在代码中,你不需要调用htonl上rec_addr,因为该值被返回inet_addr,和函数返回网络字节顺序地址.
然而,你需要调用htons上rec_port.
这些函数命名不当。Host to network并且network to host实际上是同一件事,真的应该称为“如果这是一个小字节序机器,则更改字节序”
所以在一个小端机器上你做
net, ie be, number = htonl / ntohl (le number)
Run Code Online (Sandbox Code Playgroud)
并在电线上发送 be 号码。当你从电线上得到一个大端数字时
le num = htonl/ntohl (net ,ie be, number)
Run Code Online (Sandbox Code Playgroud)
在大型机器上
net, ie be, number = htonl / ntohl (be number)
Run Code Online (Sandbox Code Playgroud)
和
be num = htonl/ntohl (net ,ie be, number)
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,你会看到这些函数什么都不做
这两个函数都反转了字节的顺序.为什么会返回论证本身?
尝试htons(ntohs(4711))和ntohs(htons(4711)).
“网络字节顺序”始终表示大字节序。
“主机字节顺序”取决于主机的体系结构。取决于CPU,主机字节顺序可能是小端,大端或其他。(g)libc适应主机架构。
因为Intel架构是低位优先的,所以这意味着两个功能都在做相同的事情:反转字节顺序。