c - 理解 htonl() 和 ntohl()

标签 c sockets networking endianness

我正在尝试使用 unix 套接字来测试将一些 udp 数据包发送到本地主机。

据我了解,在设置 ip 地址和端口以发送数据包时,我会将转换为网络字节顺序的值填充到我的 sockaddr_in 中。 我在 OSX 上,我很惊讶这个

printf("ntohl: %d\n", ntohl(4711));
printf("htonl: %d\n", htonl(4711));
printf("plain: %d\n", 4711);

打印

ntohl: 1729232896
htonl: 1729232896
plain: 4711

所以这两个函数实际上都没有返回普通值。我本来希望看到结果不同,因为 x86 是小端 (afaik),或者与实际数字 4711 相同且相同。显然我不明白什么是 htonlntohl 及其变体。我错过了什么?

相关代码是这样的:

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;
}

最佳答案

正如其他人所提到的,htonsntohs 在小端机器上反转字节顺序,并且在大端机器上是空操作。

没有提到的是这些函数采用 16 位值并返回 16 位值。如果要转换 32 位值,则需要使用 htonlntohl

这些函数的名称来自某些数据类型的传统大小。 s 代表shortl 代表longshort 通常是 16 位,而在旧系统上 long 是 32 位。

在您的代码中,您不需要在 rec_addr 上调用 htonl,因为该值是由 inet_addr 返回的,并且该函数以网络字节顺序返回地址。

但是您确实需要在 rec_port 上调用 htons

关于c - 理解 htonl() 和 ntohl(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36924598/

相关文章:

c# - 有没有办法让 UDP .net 套接字在套接字关闭时释放绑定(bind)端口?

networking - 如何在多人游戏关卡中处理众多玩家?

javascript - Python 到 JavaScript 持久连接

调用者看不到函数返回的 char 数组字符串

c - 有条件的? : expression, 后缀操作在什么时候发生?

c - 声明一个具有零值而不是随机内存的结构?

java - 如何通过socket InputStream发送XML数据

javascript - 套接字IO : Client side 'connect' event not firing when socket is already setup

sockets - 如何使用udp套接字手动发送音频数据

c - 为什么 scanf 对于 char 输入表现得很奇怪?