【问题标题】:How to retrieve the source port from a UDP packet while using recvmsg()如何在使用 recvmsg() 时从 UDP 数据包中检索源端口
【发布时间】:2025-12-18 18:00:01
【问题描述】:

我在 Linux 中有一个使用 C 的应用程序,其中我创建了一个套接字来接收 IPv6 UDP 数据包。

为了接收数据包,我使用了 recvmsg(),因为我需要检索 ifindex,我可以使用选项 IPV6_PKTINFO 从 CMSG_DATA() 中获取。现在,我还需要从 UDP 数据包中读取源端口。有没有办法得到它?

【问题讨论】:

    标签: c linux udp


    【解决方案1】:

    当然可以,recvmsg 看起来像这样:

    ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
    

    struct msghdr 包含msg_namemsg_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 使代码与地址族无关。