【发布时间】:2025-12-18 18:00:01
【问题描述】:
我在 Linux 中有一个使用 C 的应用程序,其中我创建了一个套接字来接收 IPv6 UDP 数据包。
为了接收数据包,我使用了 recvmsg(),因为我需要检索 ifindex,我可以使用选项 IPV6_PKTINFO 从 CMSG_DATA() 中获取。现在,我还需要从 UDP 数据包中读取源端口。有没有办法得到它?
【问题讨论】:
我在 Linux 中有一个使用 C 的应用程序,其中我创建了一个套接字来接收 IPv6 UDP 数据包。
为了接收数据包,我使用了 recvmsg(),因为我需要检索 ifindex,我可以使用选项 IPV6_PKTINFO 从 CMSG_DATA() 中获取。现在,我还需要从 UDP 数据包中读取源端口。有没有办法得到它?
【问题讨论】:
当然可以,recvmsg 看起来像这样:
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
而struct msghdr 包含msg_name 和msg_namelen:
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
...
所以你可以为 IPv4 地址做这样的事情:
struct sockaddr_in *src = msg->msg_name;
uint16_t port = ntohs(src->sin_port);
并针对 IPv6 地址进行相应调整 (sockaddr_in6)。
我完全忽略了 R 在 cmets 中提到的 getnameinfo。这个函数得到一个struct sockaddr *,这意味着它不依赖于地址族。该功能非常强大,但如果您想要的只是端口,您可能对NI_NUMERICSERV 感兴趣。
【讨论】:
getnameinfo 使代码与地址族无关。