【问题标题】:Why should port number be converted to Network Byte Order when binding a socket?为什么绑定套接字时要将端口号转换为网络字节顺序?
【发布时间】:2014-03-22 05:39:18
【问题描述】:

我在设置套接字的过程中遇到了这段 sn-p 代码:

#define PORT xxxx

struct sockaddr_in self;
self.sin_family = PF_INET;
self.sin_port = htons(PORT);

我知道我们需要将通过网络传输的数据的字节顺序转换为Network Byte Order,但我不明白为什么在设置套接字时我们还需要将端口号转换为该字节顺序。我的意思是,当我们绑定时,它不是“本地”的事情吗?假设我们打算绑定的端口是 1,机器实际上使用的是 little endian;现在既然我们将它转​​换为网络字节顺序,我们不会将一个完全不同的端口绑定到套接字吗?

【问题讨论】:

  • 因为这是伯克利人最初定义套接字 API 的方式?

标签: c sockets


【解决方案1】:

我想我们假设您使用的是 TCP。端口号将在数据包头中。那将被传送。所以它将按网络字节顺序排列。

【讨论】:

  • 但是在做bind的时候,会不会因为端口完全颠倒了,所以解释不一样?
  • 套接字是操作系统的一部分。但是操作系统可以在任何机器上运行。可能是一个大端机器。在使用套接字进行编程时,我们不应该编写依赖于机器的代码(但无论如何我们都无法避免),所以我们应该编写与机器无关的网络字节顺序。 IMO,这只是一个定义。
  • 一个更好的 API 设计应该是完全中立的,这样 API 的用户就不必为每个 sockaddr_in 手动处理它。但事实并非如此,现在出于兼容性原因,我们坚持使用它。
  • @JeremyFriesner,那么你们的意思是我们应该使用网络字节顺序来实现可移植性,即使这意味着牺牲在小端机器上我们实际绑定的端口与原始端口不同宏?
  • @Xufeng 您应该编写代码以使用 htons() 如您的示例所示,以便它在所有机器上都可以正常工作。 (在理想世界中你不必这样做,但在我们的现实世界中你必须这样做)
【解决方案2】:

您是在问为什么您是应用程序程序员做它而不是库在内部做它?如果是这样,我能想到的唯一技术优势是它允许应用程序进行一次转换并缓存它并多次使用它而无需多次转换。

在 TCP 上,每个连接只需要使用一次,通常不会建立数百万个连接。但在 UDP 上,您每次发送数据包时都会使用它,因此可以合理地假设您会进行数百万或数十亿次此类调用。

然后,对于无数呼叫说 sendto() 用于 UDP 或您有什么,重新排序的必要地址被提供给操作系统,操作系统可以将其直接复制到传出的网络数据包中。

在内核中执行此操作的替代方法是要求每次调用 sendto() 以一遍又一遍地将应用所知道的地址作为相同的地址,并且每次都重新转换它。

由于sendto() 从中受益,这也许是他们让 API 的其余部分以相同方式工作的充分理由。

【讨论】:

    【解决方案3】:

    您通过网络传输端口号。它是 TCP 的 IP 数据包的一部分。查找 RFC (ietf.org/rfc/rfc793.txt)

    【讨论】:

    • 问题的第二部分怎么样? hton后端口号反了,bind如何正确识别端口?
    【解决方案4】:

    struct sockaddr_in 只是struct sockaddr 的包装结构:

    struct sockaddr {
        unsigned short sa_family;
        char           sa_data[14];
    };
    

    端口号和 IP 地址在这里保存在一起。它们在sa_data[14] 中保存在一起——第一个2 bytes 保存端口号,下一个4 bytes 保存IP 地址。剩余的8 bytes 未使用。这些是您在使用sockaddr_in 时通过sin_zero[8] 清零的8 bytes

    这整个是通过网络发送的,包括网络顺序中的端口号。

    【讨论】:

      【解决方案5】:

      机器可以使用不同的小/大端编码。为了标准化,您应该在通过网络通信时使用统一编码。这就是为什么你必须将编码转换为网络字节顺序,不管它是小/大端,重要的是它是统一的,并且网络中的每个设备和软件都能正确理解。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-10
        • 2022-01-22
        • 1970-01-01
        • 1970-01-01
        • 2013-01-06
        • 1970-01-01
        • 2015-03-30
        相关资源
        最近更新 更多