为什么 recvfrom() returns 错误的发件人地址?

Why does recvfrom() returns wrong address of sender?

这个简单的 UDP 客户端:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define PORT 9877
#define BSIZE 256
#define ADDRSTRLEN 19

static char presentation[ADDRSTRLEN];
char *Inet_ntop(const void *src)
{
    if (inet_ntop(AF_INET, src, presentation, ADDRSTRLEN) == NULL)
    {
        perror("inet_ntop");
    }
    return presentation;
}

int main()
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    char recvline[BSIZE], sendline[BSIZE];

    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    //localhost
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

    socklen_t servlen = sizeof(servaddr);
    struct sockaddr *replyaddr = malloc(servlen);
    socklen_t replylen;

    while (fgets(sendline, BSIZE, stdin) != NULL)
    {
        sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, servlen);
        printf("serv addr: %s\n", Inet_ntop(&servaddr));

        //recvfrom() should return address of the host this UDP received datagram from (localhost)
        replylen = servlen;
        ssize_t bytesRead = recvfrom(sockfd, recvline, BSIZE, 0, replyaddr, &replylen);
        printf("reply addr: %s\n", Inet_ntop(replyaddr));

        recvline[bytesRead] = '[=11=]';
        puts(recvline);
    }
}

将向 127.0.0.1:9877 上的服务器(echo 服务器)发送数据报。输出是

a
serv addr: 2.0.38.149
reply addr: 2.0.38.149
a

b
serv addr: 2.0.38.149
reply addr: 2.0.38.149
b

c
serv addr: 2.0.38.149
reply addr: 2.0.38.149
c

^C

您看不到传递的服务器地址 sendto() (servaddr) 和来自 recvfrom() (replyaddr) 的地址都不是本地主机或 127.0.0.1 .什么是 2.0.38.149 ??

tcpdump:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked v1), capture size 262144 bytes
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
IP 127.0.0.1.40270 > 127.0.0.1.9877: UDP, length 2
IP 127.0.0.1.9877 > 127.0.0.1.40270: UDP, length 2
^C
6 packets captured
12 packets received by filter
0 packets dropped by kernel

这个是对的,可以看到localhost。那么什么是2.0.38.149

地址 2.0.38.149 不是随机的。我可以编译它并 运行 它多次并总是得到相同的地址,2.0.38.149。那个地址是什么?

编辑,服务器部分:

void dg_echo(int sockfd, struct sockaddr *cliaddr, socklen_t clilen)
{
    ssize_t bytesRead;
    socklen_t len;
    char buf[BSIZE];

    while (1)
    {
        len = clilen;
        bytesRead = Recvfrom(sockfd, buf, BSIZE, 0, cliaddr, &len);

        Sendto(sockfd, buf, bytesRead, 0, cliaddr, len);
    }
}


int main()
{
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;

    sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);

    Bind(sockfd, (SA *)&servaddr, sizeof(servaddr));

    dg_echo(sockfd, (SA *)&cliaddr, sizeof(cliaddr));
}

您向 inet_ntop 传递了错误的信息。

inet_ntop的第一个参数是AF_INET时,第二个参数应该是指向struct in_addr的指针。您传递的是指向 struct sockaddr_in 的指针。因此,您看到的值来自 struct sockaddr_in.

的前 4 个字节

您需要像这样调用包装函数:

Inet_ntop(&servaddr.sin_addr)