3

size_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)

参数以什么字节顺序src_addr写入?网络还是主机?recvfrom我在手册页或通过 google 和 SO 搜索时找不到这个。

4

1 回答 1

6

假设套接字是 IPv4 或 IPv6 套接字,则存储的主机和端口src_addr将按网络字节顺序排列。

这在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 主机地址。struct的s_addr成员 in_addr 包含按网络字节顺序排列的主机​​接口地址。 in_addr 应该使用 htonl(3) 分配INADDR_*值之一(例如, INADDR_LOOPBACK)或使用 inet_aton(3)、inet_addr(3)、inet_makeaddr(3) 库函数或直接使用名称解析器设置(参见 gethostbyname(3))。

ipv6 手册页有类似的措辞。

所以在读取端口号的时候,用ntohs它来解压。读取地址时,使用inet_ntop将其转换为文本形式。

于 2019-03-10T03:27:59.657 回答