【问题标题】:"address not supported by protocol" when running a client运行客户端时出现“协议不支持的地址”
【发布时间】:2013-01-23 17:57:20
【问题描述】:

这是我的问题:我正在编写一个简单的客户端,它将使用服务器的主机名和端口号作为命令行参数连接到服务器。它编译得很好,但是当我运行客户端时,我从 perror() 收到一条消息,上面写着“错误:协议不支持地址族”。不知道为什么我会收到这个错误,但我知道当我调用 connect() 时会发生错误。由于某种原因,connect 无法在我的 sockaddr_in 结构中找到地址族信息。任何帮助将非常感激。

int main(int argc, char* argv[])
{
    if(argv[1] == NULL)
    {
        printf("if 1\n");
        perror("Error: argv[1]:hostname\n");
        exit(1);
    }

    struct sockaddr_in* servaddr = getServerInfo(argv[1], argv[2]);
    int socketfd = createSocket();

    if(socketfd < 0)
    {
        printf("if 2\n");
        perror("Error: socketfd\n");
        exit(1);
    }

    int commResult = communicate(socketfd, servaddr);

    if(commResult < 0)
    {
        printf("if 3\n");
        perror("Error: communication\n");
        exit(1);
    }

    return 0;
}

struct sockaddr_in* getServerInfo(char* hostname, char* port)
{
    struct sockaddr_in* servaddr = malloc((size_t)sizeof(struct sockaddr_in));
    struct hostent *hostptr;
    hostptr = gethostbyname(hostname);

    memset((void *) servaddr, 0, (size_t)sizeof(*servaddr));
    servaddr->sin_family = (short)(AF_INET);
    memcpy((void*)& servaddr->sin_addr, (void *) hostptr->h_addr, hostptr->h_length);
    servaddr->sin_port = htons((u_short)atoi(port));

    return servaddr;
}


int createSocket()
{
    int socketfd = socket(AF_INET, SOCK_STREAM, 0);
    if(socketfd < 0)
    {
        return -1;
    }

    return socketfd;
}

int communicate(int socketfd, struct sockaddr_in* servaddr)
{
    char buffer[BUFFERSIZE];

    // connect to the server at the location displayed by TCPserver.c
    if(connect(socketfd, (struct sockaddr*)&servaddr, sizeof(*servaddr)) < 0)
    {
        printf("if 4\n");
        perror("ERROR: connecting to socket\n");
        return -1;
    }

    printf("Connected to server\n");

    strcpy(buffer, "This is the message I want the client to echo on the screen to prove that we can  communicate together.\n");

    write(socketfd, buffer, strlen(buffer)+1); 

    return 0;
}

这里也是服务器代码:

int main()
{
char * hostname = malloc(MAXSIZE * sizeof(char));
char buffer[BUFFERSIZE];

struct sockaddr_in* servaddr = getServerInfo(hostname);
int listensockfd = createSocket(servaddr), connsockfd;
printServerInfo(hostname, servaddr);

listen(listensockfd, MAX_NUM_LISTENER_ALLOWED);

connsockfd = accept(listensockfd, NULL, NULL);
read(connsockfd, buffer, BUFFERSIZE);
printf("Message: %s\n", buffer);

// free memory
free(servaddr);
free(hostname);

return 0;
} // End main

struct sockaddr_in* getServerInfo(char* hostname)
{
    struct sockaddr_in* servaddr = malloc((size_t)sizeof(struct sockaddr_in));
    gethostname(hostname, 32);
    struct hostent *hostptr;
    hostptr = gethostbyname(hostname);

        memset((void *) servaddr, 0, (size_t)sizeof(*servaddr));
        servaddr->sin_family = (short)(AF_INET);
        memcpy((void *)& servaddr->sin_addr, (void *) hostptr->h_addr, hostptr->h_length);
        servaddr->sin_port = htons((u_short)38000);

    return servaddr;
}

int createSocket(struct sockaddr_in* servaddr)
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);

    bind(listensockfd, (struct sockaddr *) &servaddr, (socklen_t)sizeof(servaddr));

    socklen_t listensocklen = sizeof(servaddr);
    getsockname(listensockfd, (struct sockaddr*)&servaddr, &listensocklen);

    return listensockfd;
}

void printServerInfo(char* hostname, struct sockaddr_in* servaddr)
{
    struct hostent *hostptr;
    hostptr = gethostbyname(hostname);

    printf("Host Name: %s\n", hostname);
    printf("Host IP: %s\n", inet_ntoa(*(struct in_addr*)*hostptr->h_addr_list));
    printf("Port Number: %d\n", htons(servaddr->sin_port));
}

【问题讨论】:

    标签: c sockets client-server runtime-error


    【解决方案1】:

    servaddr 前面有一个虚假的&amp;,它已经一个指针。您实际上是将堆栈上指针的地址传递给connect(),而不是实际的指向struct sockaddr_in 的指针。

    替换这个:

        if(connect(socketfd, (struct sockaddr*)&servaddr, sizeof(*servaddr)) < 0)
    

    用这个:

        if(connect(socketfd, (struct sockaddr*)servaddr, sizeof(*servaddr)) < 0)
    

    它会起作用的。

    在服务器中,createSocket() 中对bind()getsockname() 的调用也出现了同样的错误。此外,您在同一函数的两个位置使用sizeof(servaddr)(指针大小)而不是sizeof(*servaddr)

    请注意,我强烈建议使用现代的 getaddrinfo() API,而不是过时的 gethostbyname() 调用。

    【讨论】:

    • 感谢 Daniel Roethlisberger 的帮助。我不敢相信这是一个如此简单的错误。但是,我有一个新错误。新错误显示“连接被拒绝”。我查看了该站点上的其他帖子,他们说通常防火墙拒绝连接或端口已关闭。许多人建议我在该主机名和端口号上运行 telnet。当我这样做时,它说连接被拒绝。然而,我认为该错误与我没有正确实现服务器或客户端有关。所以我也发布了服务器代码。
    • 我认为这不可能的另一个原因是因为我在属于同一网络的主机上运行客户端和服务器。即,我当地大学的网络。
    • 您在调用createSocket() 中的bind()getsockname() 时犯了完全相同的错误。您可以通过检查您的服务器是否使用netstat 绑定到正确的地址/端口来检测到问题。
    猜你喜欢
    • 2020-12-14
    • 2013-12-20
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 2012-07-23
    相关资源
    最近更新 更多