bind() 的结构 sockaddr_in 成员字节顺序
struct sockaddr_in member byte order for bind()
我正在学习套接字编程,我对 htons()
和函数族在学习中的不一致使用感到困惑 material。我目前正在阅读 this site,其中包含以下代码段:
001 1: struct sockaddr_in adr_inet;
002 2: int adr_len;
003 3:
004 4: memset(&adr_inet,0,sizeof adr_inet);
005 5:
006 6: adr_inet.sin_family = AF_INET;
007 7: adr_inet.sin_port = ntohs(0);
008 8: adr_inet.sin_addr.s_addr = ntohl(INADDR_ANY);
009 9: adr_len = sizeof adr_inet;
在同一提到的站点上进一步向下的后续示例具有以下代码段:
030 30: struct sockaddr_in adr_inet;/* AF_INET */
...
042 42: /* Create an AF_INET address */
043 43: memset(&adr_inet,0,sizeof adr_inet);
044 44:
045 45: adr_inet.sin_family = AF_INET;
046 46: adr_inet.sin_port = htons(9000);
047 47: memcpy(&adr_inet.sin_addr.s_addr,IPno,4);
048 48: len_inet = sizeof adr_inet;
049 49:
050 50: /* Now bind the address to the socket */
051 51: z = bind(sck_inet,
052 52: (struct sockaddr *)&adr_inet,
053 53: len_inet);
问题:
为什么 ntohs()
在第一个实例中用于 adr_inet.sin_port
,而在第二个实例中使用 htons()
?
问题:
为什么 ntohs()
和 htons()
都没有用在 adr_inet.sin_family
上?
提到的站点没有解释为什么 ntohs()
或 htons()
在各自的示例中使用;它只对 "note the use of" 表示函数。
我了解字节顺序,网络字节顺序是大端顺序。我的问题更多是关于您什么时候想要 struct sockaddr_in
的网络成员与主机字节顺序?在第二个代码示例中,.sin_port
在传递给 bind()
之前设置为网络字节顺序。我可以看到以网络或主机字节顺序将数据传递给此函数的情况:bind()
是一个 "network-related" 函数,因此它可能需要以网络字节顺序的数据;另一方面 bind()
是在主机上执行的,那么为什么不应该按主机字节顺序接受数据呢?
Why is ntohs() used on adr_inet.sin_port in the first instance, but htons() in the second?
第一个是错误的,但在实践中无论如何都是有效的。
如今几乎所有机器都使用 8 位字节和一致的大端格式或一致的小端格式。对于前者,hton[sl]
和 ntoh[sl]
都是空操作;在后者 both 上颠倒了字节顺序,因此即使它们的预期语义不同,实际上也做同样的事情。因此,使用错误的一个仍然适用于您可能 运行 一个程序的所有系统。
在设计插座 API 时,情况并非总是如此;例如,当时流行的 PDP-11 有点臭名昭著地使用 'middle-endian' (!) aka 'NUXI' order for 32-bit.
Why is neither ntohs() nor htons() used on adr_inet.sin_family?
同样在古代,互联网协议栈只是几种(最多十几种)竞争网络技术中的一种。 family
字段为这些不同的协议区分了不同类型的 sockaddr_*
结构,这些协议并不都遵循互联网 'rule' 的 big-endian,至少不一致。由于 family
没有通用网络表示,他们只是按主机顺序保留它——这通常对主机软件来说更方便。
现在实际上除了 INET、INET6 和 UNIX 之外,没有人使用任何系列 -- 后者可以通过在文件系统中使用命名管道来替换,这通常至少同样好。
Why is neither ntohs()
nor htons()
used on adr_inet.sin_family
?
adr_inet.sin_family
被初始化为AF_INET
的值。这在 bits/socket.h
中定义(在您的示例中由 netinet/in.h
调用)为:
#define PF_INET 2 /* IP protocol family. */
然后,
#define AF_INET PF_INET
所以AF_INET
只是程序将关联套接字识别为TCP/IP连接的一种方式。它实际上不会保存 IPv4 地址本身的值,因此无需对其执行字节序转换。
另外,请注意,在 C 的较新迭代中,netinet/in.h
有一条评论如下:
/* Functions to convert between host and network byte order.
Please note that these functions normally take `unsigned long int' or
`unsigned short int' values as arguments and also return them. But
this was a short-sighted decision since on different systems the types
may have different representations but the values are always the same. */
extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__));
extern uint16_t ntohs (uint16_t __netshort)
__THROW __attribute__ ((__const__));
extern uint32_t htonl (uint32_t __hostlong)
__THROW __attribute__ ((__const__));
extern uint16_t htons (uint16_t __hostshort)
__THROW __attribute__ ((__const__));
而您引用的网站引用了 unsigned long
和 unsigned short
的旧用法
转换函数的数据类型。因此,您可能会遇到来自该站点的 运行 代码问题,如果
您正在使用较新版本的 C.
我正在学习套接字编程,我对 htons()
和函数族在学习中的不一致使用感到困惑 material。我目前正在阅读 this site,其中包含以下代码段:
001 1: struct sockaddr_in adr_inet;
002 2: int adr_len;
003 3:
004 4: memset(&adr_inet,0,sizeof adr_inet);
005 5:
006 6: adr_inet.sin_family = AF_INET;
007 7: adr_inet.sin_port = ntohs(0);
008 8: adr_inet.sin_addr.s_addr = ntohl(INADDR_ANY);
009 9: adr_len = sizeof adr_inet;
在同一提到的站点上进一步向下的后续示例具有以下代码段:
030 30: struct sockaddr_in adr_inet;/* AF_INET */
...
042 42: /* Create an AF_INET address */
043 43: memset(&adr_inet,0,sizeof adr_inet);
044 44:
045 45: adr_inet.sin_family = AF_INET;
046 46: adr_inet.sin_port = htons(9000);
047 47: memcpy(&adr_inet.sin_addr.s_addr,IPno,4);
048 48: len_inet = sizeof adr_inet;
049 49:
050 50: /* Now bind the address to the socket */
051 51: z = bind(sck_inet,
052 52: (struct sockaddr *)&adr_inet,
053 53: len_inet);
问题:
为什么 ntohs()
在第一个实例中用于 adr_inet.sin_port
,而在第二个实例中使用 htons()
?
问题:
为什么 ntohs()
和 htons()
都没有用在 adr_inet.sin_family
上?
提到的站点没有解释为什么 ntohs()
或 htons()
在各自的示例中使用;它只对 "note the use of" 表示函数。
我了解字节顺序,网络字节顺序是大端顺序。我的问题更多是关于您什么时候想要 struct sockaddr_in
的网络成员与主机字节顺序?在第二个代码示例中,.sin_port
在传递给 bind()
之前设置为网络字节顺序。我可以看到以网络或主机字节顺序将数据传递给此函数的情况:bind()
是一个 "network-related" 函数,因此它可能需要以网络字节顺序的数据;另一方面 bind()
是在主机上执行的,那么为什么不应该按主机字节顺序接受数据呢?
Why is ntohs() used on adr_inet.sin_port in the first instance, but htons() in the second?
第一个是错误的,但在实践中无论如何都是有效的。
如今几乎所有机器都使用 8 位字节和一致的大端格式或一致的小端格式。对于前者,hton[sl]
和 ntoh[sl]
都是空操作;在后者 both 上颠倒了字节顺序,因此即使它们的预期语义不同,实际上也做同样的事情。因此,使用错误的一个仍然适用于您可能 运行 一个程序的所有系统。
在设计插座 API 时,情况并非总是如此;例如,当时流行的 PDP-11 有点臭名昭著地使用 'middle-endian' (!) aka 'NUXI' order for 32-bit.
Why is neither ntohs() nor htons() used on adr_inet.sin_family?
同样在古代,互联网协议栈只是几种(最多十几种)竞争网络技术中的一种。 family
字段为这些不同的协议区分了不同类型的 sockaddr_*
结构,这些协议并不都遵循互联网 'rule' 的 big-endian,至少不一致。由于 family
没有通用网络表示,他们只是按主机顺序保留它——这通常对主机软件来说更方便。
现在实际上除了 INET、INET6 和 UNIX 之外,没有人使用任何系列 -- 后者可以通过在文件系统中使用命名管道来替换,这通常至少同样好。
Why is neither
ntohs()
norhtons()
used onadr_inet.sin_family
?
adr_inet.sin_family
被初始化为AF_INET
的值。这在 bits/socket.h
中定义(在您的示例中由 netinet/in.h
调用)为:
#define PF_INET 2 /* IP protocol family. */
然后,
#define AF_INET PF_INET
所以AF_INET
只是程序将关联套接字识别为TCP/IP连接的一种方式。它实际上不会保存 IPv4 地址本身的值,因此无需对其执行字节序转换。
另外,请注意,在 C 的较新迭代中,netinet/in.h
有一条评论如下:
/* Functions to convert between host and network byte order.
Please note that these functions normally take `unsigned long int' or
`unsigned short int' values as arguments and also return them. But
this was a short-sighted decision since on different systems the types
may have different representations but the values are always the same. */
extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__));
extern uint16_t ntohs (uint16_t __netshort)
__THROW __attribute__ ((__const__));
extern uint32_t htonl (uint32_t __hostlong)
__THROW __attribute__ ((__const__));
extern uint16_t htons (uint16_t __hostshort)
__THROW __attribute__ ((__const__));
而您引用的网站引用了 unsigned long
和 unsigned short
的旧用法
转换函数的数据类型。因此,您可能会遇到来自该站点的 运行 代码问题,如果
您正在使用较新版本的 C.