【问题标题】:Bad address received from recvfrom: why?从 recvfrom 收到错误地址:为什么?
【发布时间】:2018-07-01 11:09:00
【问题描述】:

我正在编写一个函数,它应该执行一些操作,然后返回(使用它的参数)与函数内部的recvfrom 交互(即使用sendto)的设备的地址。

这是我调用函数的方式,之前实例化了cliaddr

struct sockaddr_in cliaddr;
memset((void *) &cliaddr, 0, sizeof(cliaddr));
rcv_string(sockfd, &return_string, &cliaddr);
// Here I'll need to use cliaddr, that's why I need it outside too

下面是函数的实现:

int rcv_string(int sockfd, char **return_string, struct sockaddr_in *sndaddr) {
    // ...
    char buff[PACKETSZ + 2];
    memset(&buff, 0, sizeof(buff)); // Clean buffer
    socklen_t *plen = malloc(sizeof(struct sockaddr *));
    if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, plen)) < 0) {
            perror("recvfrom");
            return -1;
    }
    char *snd_ip = malloc(INET_ADDRSTRLEN * sizeof(char));
    if (inet_ntop(AF_INET, &((*sndaddr).sin_addr.s_addr), snd_ip, INET_ADDRSTRLEN * sizeof(char)) == NULL) {
            perror("inet_ntop");
            return -1;
    }
    printf("Received '%s' from '%s'.\n", buff, snd_ip);
    // ...
}

现在,即使发送设备的 IP 地址是 192.168.1.251,我也会得到以下输出:

Received '0packetx' from '0.0.0.0'.

接收到的缓冲区格式正确,但地址明显错误。为什么?和函数外定义地址变量有关系吗?

编辑

如果在cliaddrmemset 之后,我还要添加这 3 行:

cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(SERV_PORT);

我得到一个随机行为。有时我得到0.0.0.0,有时是127.0.0.1,有时是正确的地址(192.168.1.251)。

【问题讨论】:

  • 次要:(*sndaddr).sin_addr = sndaddr-&gt;sin_addr
  • 仅仅因为你有接受指针参数的函数并不意味着你需要使用动态内存分配。通常你不会。相反,如果可以创建指向适当类型的普通对象的指针,请使用地址运算符 (&amp;)。或者有时使用数组是合适的。
  • 谢谢@EugeneSh。和 @JohnBollinger 为您的 cmets。从现在开始,我将尝试按照您的提示进行操作。你知道我为什么得到0.0.0.0吗?这真的让我很困惑。 :(

标签: c sockets pointers recvfrom


【解决方案1】:

您将错误的长度传递给 recvfrom

  socklen_t *plen = malloc(sizeof(struct sockaddr *));
    if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, plen))

为什么你的malloc是个谜,但你需要

socklen_t *plen = malloc(sizeof(socklen_t));
*plen = sizeof(struct sockaddr_in );

更简单的是

      socklen_t plen = sizeof(struct sockaddr_in);
   if ((recvfrom(sockfd, buff, sizeof(buff), 0, (struct sockaddr *) sndaddr, &plen))

【讨论】:

  • 我很惊讶这个问题没有得到更多的关注。我已经坚持了好几天了,在阅读了这篇文章之后,我意识到我用作recvfrom 示例的所有 3 个来源都是错误的!他们都没有初始化sockaddr_in的实际长度!鬼鬼祟祟的事情是,不这样做仍然会在大约 50% 的时间里工作,并且有效载荷似乎总是完好无损地到达。
【解决方案2】:

如果你用有效的 sizeof 数据填充 plen,它应该可以工作。

*plen = sizeof(struct sockaddr_in);

你可以把它放在 recvfrom 调用之前。

【讨论】:

  • 你是对的,谢谢你的回答:我修好了,但是错误的ip问题当然没有解决。
猜你喜欢
  • 1970-01-01
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
  • 2014-06-01
相关资源
最近更新 更多