【发布时间】:2019-07-31 17:18:52
【问题描述】:
size_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
src_addr 参数以什么字节顺序写入?网络还是主机?我在 recvfrom 手册页或通过 google 和 SO 搜索时找不到这个。
【问题讨论】:
size_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
src_addr 参数以什么字节顺序写入?网络还是主机?我在 recvfrom 手册页或通过 google 和 SO 搜索时找不到这个。
【问题讨论】:
假设套接字是 IPv4 或 IPv6 套接字,则存储在 src_addr 中的主机和端口将按网络字节顺序排列。
这在man page for IPv4 (man 7 ip) 中记录如下:
地址格式
IP 套接字地址被定义为 IP 接口的组合 地址和一个 16 位的端口号。基本IP协议不 提供端口号,它们由更高级别的协议实现
像 udp(7) 和 tcp(7)。在原始套接字上,sin_port 设置为 IP 协议。struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET */ in_port_t sin_port; /* port in network byte order */ struct in_addr sin_addr; /* internet address */ }; /* Internet address. */ struct in_addr { uint32_t s_addr; /* address in network byte order */ };
sin_family始终设置为AF_INET。这是必需的;在 Linux 中 2.2 大多数网络功能在缺少此设置时返回EINVAL。sin_port包含网络字节顺序的端口。 低于 1024 的端口号称为特权端口(或有时: 保留端口)。只有一个特权进程(在 Linux 上:一个进程 在用户命名空间中具有 CAP_NET_BIND_SERVICE 功能 管理其网络命名空间)可以绑定(2)到这些套接字。 请注意,原始 IPv4 协议本身没有端口的概念, 它们仅由高级协议(如 tcp(7) 和 udp(7)。
sin_addr是 IP 主机地址。s_addr结构体成员in_addr包含网络字节顺序的主机接口地址。in_addr应分配为INADDR_*值之一(例如,INADDR_LOOPBACK) 使用 htonl(3) 或使用 inet_aton(3) 设置, inet_addr(3)、inet_makeaddr(3) 库函数或直接使用 名称解析器(参见 gethostbyname(3))。
ipv6 手册页有类似的措辞。
所以在读取端口号的时候,使用ntohs解压即可。读取地址时,使用inet_ntop转成文本格式。
【讨论】: