3

我们知道 Recvfrom 函数有以下概要

    SYNOPSIS
#include <sys/socket.h>
int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);

from 具有 sockaddr 的结构。

struct sockaddr {
                __uint8_t   sa_len;     // total length
                sa_family_t sa_family;  // [XSI] address family 
                char        sa_data[14];    // [XSI] addr value (actually larger)
            };

但 sockaddr 似乎无法保存 IP 地址。

recvfrom 不应该使用 struct socaddr_in * from 因为

        struct sockaddr_in {
            __uint8_t   sin_len;
            sa_family_t sin_family;
            in_port_t   sin_port;
            struct  in_addr sin_addr;
            char        sin_zero[8];
        };

sin_addr 将给出 IP 地址。这是一个有效的假设吗?

4

3 回答 3

10

出于历史原因,该from参数被定义为sockaddr*支持 IPv6 之前的遗留代码。sock_addr是相当不可知的,但它也不足以处理较新的套接字类型。任何具有sockaddr*参数的套接字函数实际上都期望任何sockaddr基于 - 的结构都适合正在使用的套接字类型。

如果您从 IPv4 套接字读取,它需要一个sockaddr_in*,例如:

struct sockaddr_in from;
socklen_t len = sizeof(from);
recvfrom(s, ..., (struct sockaddr*)&from, &len); 
// use from.sin_addr and from.sin_port as needed...

如果您从 IPv6 套接字读取,则它需要一个sockaddr_in6*,例如:

struct sockaddr_in6 from;
socklen_t len = sizeof(from);
recvfrom(s, ..., (struct sockaddr*)&from, &len); 
// use from.sin6_addr and from.sin6_port as needed...

如果您想编写支持多种协议的代码,请sockaddr_storage根据需要使用和类型转换,例如:

struct sockaddr_storage from;
socklen_t len = sizeof(from);
recvfrom(s, ..., (struct sockaddr*)&from, &len); 
switch (from.ss_family)
{
    case AF_INET:
        // use ((struct sockaddr_in*)&from) as needed...
        break;
    case AF_INET6:
        // use ((struct sockaddr_in6*)&from) as needed...
        break;
    ...
}

这同样适用于其他sockaddr基于函数,包括connect()bind()和。accept()sendto()

于 2013-09-25T04:46:06.937 回答
0

您可以进行如下操作:

struct scokaddr_in A;
char buf[200];
int len;
recvfrom(fd, buf, 200, 0, (struct sockaddr*)&A, &len);
//from ip-address is stored in A.sin_addr...
于 2013-09-25T02:53:59.353 回答
0

如果要将 IP 地址保存为字符串,可以使用该inet_ntop()函数。Beej 的指南提供了一些关于如何使用它的有用信息,以及与 IP 版本无关的示例。

于 2021-08-25T02:46:55.787 回答