我在 Linux (Centos) 下的 C 中运行时遇到“无法分配请求的地址”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8799216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:00:24  来源:igfitidea点击:

I got error in run time that "Cannot assign requested address" in C under Linux (Centos)

clinuxcentos

提问by gaurav bhadani

When I assign this address , it says cannot assign requested address. But when I put local address (127.0.0.1) it accepts it. Why???

当我分配这个地址时,它说cannot assign requested address。但是当我输入本地地址(127.0.0.1)时,它会接受它。为什么???

char* hostname = "192.168.1.8"; 

int sockfd;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t addr_len;
int numbytes;
char buf[MAXBUFLEN];
int port =5000;

if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("socket");
    exit(1);
}
try
{
    my_addr.sin_family = AF_INET;        // host byte order
    my_addr.sin_addr.s_addr = inet_addr(hostname);

    printf("Accepted/n");
    // automatically fill with my IP
    my_addr.sin_port = htons(5000);  // short, network byte order
    memset(&(my_addr.sin_zero), '
memset (&my_addr, 0, sizeof (my_addr));
my_addr.sin_family      = AF_INET;
my_addr.sin_addr.s_addr = inet_addr (hostname);
my_addr.sin_port        = htons (5000);
', 8); // zero the rest of the struct if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } while (1) { addr_len = sizeof(struct sockaddr); if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *)&their_addr, &addr_len)) == -1) { perror("recvfrom"); exit(1); } //printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr)); //printf("packet is %d bytes long\n",numbytes); buf[numbytes] = '
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
'; //printf("packet contains \"%s\"\n",buf); } close(sockfd); } catch(...) {

回答by paxdiablo

If the error is happening on the bind(it's not that obvious based on your question content since the error message you state does not appear in the code), it's likely to be because the address is not available.

如果错误发生在bind(根据您的问题内容并不那么明显,因为您声明的错误消息没有出现在代码中),很可能是因为地址不可用。

That's usually because it's already in use, or not available on the current host.

这通常是因为它已经在使用中,或者在当前主机上不可用。

With a few exceptions, you can generally only bind to IP addresses that are assigned to your local interfaces. You should check that 192.168.1.8is in that class. It's a given that 127.0.0.1will be a local interface (hence why it works), and that INADDR_ANYwill work as well - that's probably the "address" you should use unless you have a real specific need to limit yourself to one interface.

除了少数例外,您通常只能绑定到分配给本地接口的 IP 地址。你应该检查那个192.168.1.8在那个班上。这是一个给定127.0.0.1的本地接口(因此它可以工作),并且它INADDR_ANY也可以工作 - 这可能是您应该使用的“地址”,除非您有真正的特定需要将自己限制在一个接口上。

You should check the errnofollowing the failing function and match it against the possibilities.

您应该检查errno以下失败的功能并将其与可能性进行匹配。



As an aside, and this is probably irrelevant to your problem, the way in which you initialise the sockaddr_instructure (setting fields then clearing the rest) seems to be less than portable to me.

顺便说一句,这可能与您的问题无关,您初始化sockaddr_in结构的方式(设置字段然后清除其余部分)对我来说似乎不太便携。

I think it would be safer to clear the lot then simply set what you desire after that, something like:

我认为清除地段然后简单地设置你想要的东西会更安全,比如:

int main (int argc, char *argv[]) {
    int sockfd;
    struct sockaddr_in me;

    if (argc < 2) {
        printf ("Need argument with IP address\n");
        return 1;
    }

    if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
        perror("socket");
        return 1;
    }

At least that way, the order of fields within the structure won't affect your code.

至少这样,结构中字段的顺序不会影响您的代码。



You can see the problem with the following code. First off, the requisite headers:

您可以通过以下代码看到问题。首先,必要的标题:

    memset (&me, 0, sizeof (me));
    me.sin_family = AF_INET;
    me.sin_addr.s_addr = inet_addr (argv[1]);
    me.sin_port = htons (5000);

    if (bind (sockfd, (struct sockaddr *)&me, sizeof(struct sockaddr)) == -1)
    {
        fprintf (stderr, "errno = %d ", errno);
        perror("bind");
        exit(1);
    }

    close(sockfd);

    return 0;
}

Then the argument checking and socket creation.

然后是参数检查和套接字创建。

pax> ifconfig | grep 'inet addr'
      inet addr:192.168.0.101  Bcast:192.168.0.255   Mask:255.255.255.0
      inet addr:127.0.0.1                            Mask:255.0.0.0
      inet addr:192.168.99.1   Bcast:192.168.99.255  Mask:255.255.255.0
      inet addr:192.168.72.1   Bcast:192.168.72.255  Mask:255.255.255.0

pax> ./testprog 127.0.0.1

pax> ./testprog 192.168.0.101

pax> ./testprog 192.168.0.102
errno = 99 bind: Cannot assign requested address

pax> grep '#define.*99' /usr/include/asm-generic/errno.h
#define     EADDRNOTAVAIL     99     /* Cannot assign requested address */

Then the binding itself:

然后绑定本身:

##代码##

When you run that with certain arguments, you can see it works okay for the ones where the IP addresses belong to local interfaces (127.0.0.1and 192.168.0.101) but not for those that do not, like 192.168.0.102:

当您使用某些参数运行它时,您可以看到它适用于 IP 地址属于本地接口 (127.0.0.1192.168.0.101) 的那些,但不适用于那些不属于的,例如192.168.0.102

##代码##

And, from the link to the bindman page above, we see:

而且,从bind上面的手册页链接,我们看到:

EADDRNOTAVAIL
       A nonexistent interface was requested or the requested address was not local.

EADDRNOTAVAIL
       请求了一个不存在的接口或请求的地址不是本地的。