绑定到 INADDR_LOOPBACK 时“无法分配请求的地址”,但 INADDR_ANY 可以工作

asy*_*nts 3 c linux tcp

注意:我找到了针对这个问题研究的解决方案。下一个犯这个错误的人希望在花太多时间在这个问题上之前发现这个问题。

我一直在尝试在Linux系统上实现TCP服务器。问题是我收到一条非常通用的错误消息,但没有揭示问题的原因:

$ gcc -Wall -Wextra main.c
$ ./a.out
bind: Cannot assign requested address
Run Code Online (Sandbox Code Playgroud)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1) {
        fprintf(stderr, "socket: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = 8080;
    addr.sin_addr.s_addr = INADDR_LOOPBACK;

    if(bind(sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) {
        fprintf(stderr, "bind: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }

    if(close(sockfd) != 0) {
        fprintf(stderr, "close: %s\n", strerror(errno));
        return EXIT_FAILURE;
    }
}
Run Code Online (Sandbox Code Playgroud)

该网站上有无数的问题描述了类似的问题,但这里的关键是当我尝试绑定到INADDR_ANY而不是INADDR_LOOPBACK. 我发现了一些有这个问题的问题,但反过来就有点奇怪了。

导致此错误消息的可能原因有哪些?

asy*_*nts 5

我分配的端口和地址错误:

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 8080;
addr.sin_addr.s_addr = INADDR_LOOPBACK;
Run Code Online (Sandbox Code Playgroud)

应该

struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
Run Code Online (Sandbox Code Playgroud)

htons代表“主机到网络短”和htonl“主机到网络长”,指的是地址和端口编码的字节顺序。

INADDR_ANY是地址0.0.0.0,字节顺序在这里并不重要。是被错误理解为 的INADDR_LOOPBACK地址。127.0.0.11.0.0.127