我在我的程序中使用 recvfrom 从我在 src_addr 中指定的服务器获取 DGRAM 数据。但是,我不确定为什么需要初始化并传入 addrlen。
我阅读了手册页,但我并没有真正理解它的含义。
If src_addr is not NULL, and the underlying protocol provides the source address, this source address is filled in. When src_addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL. The argument addrlen is a value-result argument, which the caller should initialize before the call to the size of the buffer associated with src_addr, and modified on return to indicate the actual size of the source address. The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.
我猜这与 src_addr 是 ipv4 或 ipv6 有关。这是正确的吗?
谢谢!
最佳答案
也许您的理解有误。谈:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
src_addr
不是用来交in你想收听的地址,而是你提供的一个存储位置得到实际的源地址 out。
因此,如果您将 src_addr
设置为 NULL,因为您根本对地址不感兴趣,您不必关心 addrlen
因为它不会被使用无论如何。
另一方面,如果你想知道源地址,你不仅要提供一个存储位置,还要告诉你提供的存储位置有多大。
这就是为什么你应该将 *addr_len
初始化为你分配的缓冲区大小。
在您调用后,addrlen
指向的值将通知您分配用于存储源地址的空间中有多少(如果有)实际填充了数据。
关于尺寸
struct sockaddr 和来回传递大小的整个麻烦与这样一个事实有关,即使它们在网络套接字中使用得最多,但其意图是更笼统的概念。
以 unix 域套接字为例,因为它们是通过文件系统实现的,它们需要一个与基于 IP 的网络已知的完全不同的寻址方案。这里使用的 sockaddr 的类型是:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
sun_path[UNIX_PATH_MAX]; /* pathname */
};
将此与基于 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 */
};
应该清楚两者没有太多共同点。
socket 的设计能够适应这两种情况。
关于c - recvfrom() 中的 addrlen 字段是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15168095/