Espen HK
Espen HK

Reputation: 13

listen(): invalid argument

Trying to create a server-client application, and I'm having quite a bit of trouble setting up the connection on the server-side. After setting up the socket, and bind()ing the socket, my listen()-call fails with the error message

listen: Invalid argument

which I get from perror()-ing the case where listen() returns -1.

The synopsis of the program is the following: I use getaddrinfo() to generate a linked list of struct addrinfo's, loop through that until I find one that I can successfully create a socket with, then bind() and finally listen().

The listen() call goes as follows:

if ((status = listen(socket_fd, BACKLOG_SIZE)) == -1) {
    perror("listen");
    close(socket_fd);
    freeaddrinfo(res);
    exit(EXIT_FAILURE);
}

To be sure, I've printed the values of socket_fd and BACKLOG_SIZE, turning out to be 3 and 5, respectively. Have been debugging for hours now, and I simply cannot find out where the problem lies. Haven't found anyone with the same issue on stackOverflow, either...

Thank you in advance for any help!

Full program:

int main(int argc, char* argv[]) {
    int port_no = server_usage(argc, argv);
    ready_connection(port_no);

    /* Synopsis:
    getaddrinfo()
    socket()
    bind()
    listen()
    accept()
    */
    int socket_fd = setup_socket(NULL, port_no);

    struct sockaddr_storage their_addr;
    socklen_t addr_size = sizeof(their_addr);
    int new_fd = 0;

    // Allow reuse of sockets
    int activate=1;
    setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &activate,     sizeof(int));

    if ((status = bind(socket_fd, res->ai_addr, res->ai_addrlen)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if ((status = connect(socket_fd, res->ai_addr, res->ai_addrlen)) == -1) {
        perror("connect");
        close(socket_fd);
        freeaddrinfo(res); // free the linked-list
        exit(EXIT_FAILURE);
    }

    if ((status = listen(socket_fd, BACKLOG_SIZE)) == -1) {
        perror("listen");
        close(socket_fd);
        freeaddrinfo(res); // free the linked-list
        exit(EXIT_FAILURE);
    }

    if ((new_fd == accept(socket_fd, (struct sockaddr *)&their_addr, &addr_size)) == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    char buffer[BUFSIZE];
    recv(new_fd, buffer, BUFSIZE, 0);

    close(socket_fd);
    close(new_fd);
    freeaddrinfo(res); // free the linked-list

    return 0;
}

setup_socket()-function:

int setup_socket(char* hostname, int port_no) {
    // hints is mask struct, p is loop variable
    struct addrinfo hints, *p;

    memset(&hints, 0, sizeof hints); // make sure the struct is empty
    // TODO IPv6-support?
    hints.ai_family = AF_INET;     // only IPv4 supported
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
    hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

    char port_str[6]; // max port size is 5 digits + 0-byte
    memset(port_str, 0, 6);
    sprintf(port_str, "%d", port_no);

    if ((status = getaddrinfo(hostname, port_str, &hints, &res)) == -1) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(EXIT_FAILURE);
    }

    int socket_fd = 0;

    for (p = res; p != NULL; p = p->ai_next) {
        if ((socket_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
            perror("socket");
            exit(EXIT_FAILURE);
        }
    }

    if (socket_fd == 0) {
        errno = ENOTSOCK;
        perror("no socket");
        exit(EXIT_FAILURE);
    }

    return socket_fd;
}

Upvotes: 1

Views: 3194

Answers (1)

keithmo
keithmo

Reputation: 4943

You cannot connect(), then listen() on the same socket. Lose the connect().

Upvotes: 4

Related Questions