3

我在我的程序中使用 recvfrom 从我在 src_addr 中指定的服务器获取 DGRAM 数据。但是,我不确定为什么需要初始化并传入 addrlen。

我阅读了手册页,但我并没有真正理解它的含义。

如果 src_addr 不为 NULL,且底层协议提供源地址,则填写此源地址。当 src_addr 为 NULL 时,不填写;在这种情况下,不使用 addrlen,也应该为 NULL。参数 addrlen 是一个 value-result 参数,调用者应该在调用之前将其初始化为与 src_addr 关联的缓冲区的大小,并在返回时修改以指示源地址的实际大小。如果提供的缓冲区太小,返回的地址会被截断;在这种情况下,addrlen 将返回一个大于提供给调用的值。

我猜这与 src_addr 是 ipv4 或 ipv6 有关。它是否正确?

谢谢!

4

2 回答 2

7

也许您的身边有误解。谈论:

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

src_addr不是用来交你想听的地址,而是你提供的一个存储位置,用来获取实际交出地址

因此,如果您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 */
};

应该清楚两者没有太多共同点。

插座的设计能够适应这两种情况。

于 2013-03-01T23:02:19.003 回答
3
ssize_t recvfrom(int socket, void *buffer, size_t length, int flags,
         struct sockaddr *address, socklen_t *address_len);`

参数指定结构的address_len长度,address即从指示的起始地址开始使用的字节数address(内存位置的起始地址 + 保存该值的起始地址的字节数)

结构定义在/usr/include/bits/socket.h

/* Structure describing a generic socket address.  */
struct sockaddr
{
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.      */  
    char sa_data[14];       /* Address data.  */
};

因此,该sa_data字段保存其长度由address_len参数指示的地址数据(数据的起始地址)。

...每当一个函数说它需要一个 struct sockaddr* 时,您可以轻松安全地将 struct sockaddr_in*、struct sockaddr_in6* 或 struct sockadd_storage* 转换为该类型。

因此,如手册页和问题评论中的@WhozCraig 所示,当方法返回时,此字段将更新为实际大小。

更多信息

于 2013-03-01T22:50:19.543 回答