Search code examples
clinuxtcp

"Cannot assign requested address" when binding to INADDR_LOOPBACK, but INADDR_ANY works


Note: I found the solution which researching for this question. The next one making this mistake will hopefully discover this question before spending to much time on this.

I've been trying to implement a TCP server on a Linux system. The problem is that I receive a very generic error message that doesn't reveal the cause of the problem:

$ gcc -Wall -Wextra main.c
$ ./a.out
bind: Cannot assign requested address
#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;
    }
}

There are countless questions on this site that describe a similar problem, but the key thing here is that it works when I try to bind to INADDR_ANY instead of INADDR_LOOPBACK. I found a few questions that had this issue, but the other way around which is a bit weird.

What are possible causes for this error message?


Solution

  • I've been assigning the port and address wrong:

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

    should be

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8080);
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    

    htons stands for "host to network short" and htonl stands for "host to network long", and are refering to the byte order in which the address and port are encoded.

    INADDR_ANY is the address 0.0.0.0, the byte order doesn't matter here. INADDR_LOOPBACK is the address 127.0.0.1 which was incorrectly understood as 1.0.0.127.