套接字的recvfrom函数可以提取发送者IP地址吗?

lil*_*lzz 2 c sockets

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

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

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)
            };
Run Code Online (Sandbox Code Playgroud)

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

不应该使用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];
        };
Run Code Online (Sandbox Code Playgroud)

然后sin_addr将提供IP地址。这是一个有效的假设吗?

Rem*_*eau 5

出于历史原因,将该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...
Run Code Online (Sandbox Code Playgroud)

如果您是从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...
Run Code Online (Sandbox Code Playgroud)

如果要编写支持多种协议的代码,请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;
    ...
}
Run Code Online (Sandbox Code Playgroud)

这同样适用于其他sockaddr基于功能,包括connect()bind()accept()sendto()


nit*_*712 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...
Run Code Online (Sandbox Code Playgroud)