demonSlayer
demonSlayer

Reputation: 315

can't bind to socket

Code :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
// #include <thread>
#include <arpa/inet.h>
#include <iostream>

using namespace std;

#define PORT 8888
#define BACKLOG 5

int main(int argc, char const *argv[]) {

    int status;
    struct addrinfo hints,
                    *res,
                    *temp;

    char ipstr [INET6_ADDRSTRLEN];
    int socket_fd;

    memset (&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;        // Allows both IPv4 and IPv6
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;        // Allows automatic fill-up of IP (allows using localhost)

    if ((status = getaddrinfo (NULL , "8000", &hints, &res)) != 0 ) {
        cout << "[-] Error: " << gai_strerror (status) << endl;
        exit (EXIT_FAILURE);
    }

    socket_fd = socket (res->ai_family, res->ai_socktype, res->ai_protocol);
    if (socket_fd == -1) {
        cout << "[-] Error : Socket couldn't be created" << endl;
        exit (EXIT_FAILURE);
    }

    if (bind (socket_fd, res->ai_addr, res->ai_addrlen) == -1 ) {
        cout << "[-] Error: Failed to bind to port" << endl;
        exit (EXIT_FAILURE);
    }

    if (connect (socket_fd, res->ai_addr, res->ai_addrlen) == -1) {
        cout << "[-] Error: Failed to connect to remote user" << endl;
        exit (EXIT_FAILURE);
    }

    freeaddrinfo (res);        // free the linked list returned by getaddrinfo ()
    return 0;
}

The code is returning :
[-] Error: Failed to bind to port

It doesn't matter if I put NULL on getaddrinfo ()'s first parameter (making it listen to localHost) or to provide some address, it isn't able to bind port to socket. The port is available as I have tried by changing the value of port. What is wrong with the code ?

Upvotes: 0

Views: 10732

Answers (2)

karastojko
karastojko

Reputation: 1181

The code is fine, so when the first time is executed everything works as expected. However, the subsequent execution of the same program will report

[-] Error: Failed to bind to port

If you run netstat --tcp --numeric | grep 8000 you will see that the socket on the port 8000 is in TIME_WAIT state:

bash-4.2$ netstat --tcp --numeric | grep 8000
tcp        0      0 127.0.0.1:8000          127.0.0.1:8000          TIME_WAIT

meaning that connection is closed, so it will be terminated in the timeout specified by the OS (four minutes by default). After the timeout expires, the program executes without the error (again only once).

Upvotes: 4

Sam Varshavchik
Sam Varshavchik

Reputation: 118292

Something here is not making sense. The shown code attempts to bind a socket to a port, then immediately connect() to the same port. So, even if the bind works, connect() will fail anyway, because nothing is listening on that port.

Now, the most likely reason why bind() is failing is because after a socket gets terminated unexpectedly, the kernel will not allow the same port to be reused for a minute or so, for a number of security-related reasons that are too boring to discuss. The first time this code runs, the bind should succeed, but connect() will fail, and the program will exit; then for the next minute or so, rerunning it will result in a bind() failure from the kernel refusing to reuse the port.

To prevent this, you must explicitly set the SO_REUSEADDR socket option. You will find plenty of examples in Google. This will allow you to rebind the same port immediately. Now, all you'll need to do is to figure out what exactly you hoped to accomplish with that connect() call...

Upvotes: 1

Related Questions