Dries
Dries

Reputation: 1005

Error 10061 when trying to connect with winsock

I have a client and server running on the same computer. Client connects to 127.0.0.1 with port 80. Server is listening on port 80 at the same time.

When I start the client and try to connect it throws error 10061 (Actively refused by target computer). I tried shutting down my local firewall but that didn't change anything. I'm definitely stuck with this. Here's the code that connects to the server:

void Base::Connect(string ip, string port)
{
    int status;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo hints;
    struct addrinfo *servinfo;  // will point to the results

    memset(&hints, 0, sizeof hints); // make sure the struct is empty
    hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

    // get ready to connect
    status = getaddrinfo(ip.c_str(), port.c_str(), &hints, &servinfo);

    // Socket Setup
    if ((ConnectSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == INVALID_SOCKET)
    {
        printf("[NETWORKING] An error occured when setting up socket\n");
    }

    // Connect
    WSACleanup();
    if (connect(ConnectSocket, servinfo->ai_addr, (int)servinfo->ai_addrlen) == SOCKET_ERROR)
    {
        int error = WSAGetLastError();
        printf("Connect error: ", error);
    }
}

And here's the code from the server that listens for incoming connections:

int _tmain(int argc, _TCHAR* argv[])
{
// WINDOWS SETUP
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) 
{
    fprintf(stderr, "WSAStartup failed.\n");
    exit(1);
}

// PREPARE TO LAUNCH
int status;
struct sockaddr_storage their_addr;
socklen_t addr_size;
int sockfd, new_fd = 0;

struct addrinfo hints;
struct addrinfo *servinfo;  // will point to the results

memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

if ((status = getaddrinfo(NULL, "80", &hints, &servinfo)) != 0) 
{
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    getchar();
    exit(1);
}

// GET THE FILE DESCRIPTOR  
SOCKET mSocket = INVALID_SOCKET;
mSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);

// WHAT PORT AM I ON
bind(mSocket, servinfo->ai_addr, servinfo->ai_addrlen);

int backlog = 2;
listen(mSocket, backlog);

// SERVER STARTED LISTENING SUCCESFULLY
printf("Server is listenening...\n");

// ACCEPT
printf("Server starts accepting clients...\n");
addr_size = sizeof their_addr;
new_fd = accept(mSocket, (struct sockaddr*)&their_addr, &addr_size);

printf("Server ended");
getchar();

// lose the pesky "Address already in use" error message
char yes='1';

if (setsockopt(mSocket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
} 

return 0;
}

Any help is welcome! Thanks in advance

Upvotes: 2

Views: 4277

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598001

On the client side:

  1. do not call WSACleanup() before calling connect().
  2. You are not doing any error handling on getaddrinfo().
  3. you are not setting the ai_flags to match your input values (like AI_NUMERICHOST).
  4. you are not freeing the memory that getaddrinfo() returns.
  5. you are not taking into account that you are specifying AF_UNSPEC to getaddrinfo() so it may return multiple addresses. You should try to connect to all of them until one succeeds.

Try this instead:

void Base::Connect(string ip, string port)
{
    int status, error;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo hints = {0};
    struct addrinfo *servinfo;  // will point to the results

    hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
    hints.ai_flags = AI_NUMERICHOST; // parse an IP address
    //hints.ai_flags |= AI_NUMERICSERV; // parse a port number (not supported on Windows)

    // get ready to connect
    status = getaddrinfo(ip.c_str(), port.c_str(), &hints, &servinfo);
    if (status != 0)
    {
        printf("getaddrinfo error: (%d) %s\n", status, gai_strerror(status));
        return;
    }

    addrinfo *addr = servinfo;
    do
    {
        // Socket Setup
        ConnectSocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET)
        {
            printf("socket error: %d\n", WSAGetLastError());
        }
        else
        {
            // Connect
            if (connect(ConnectSocket, addr->ai_addr, addr->ai_addrlen) != SOCKET_ERROR)
            {
                printf("connected to server\n");
                break;
            }

            printf("connect error: %d\n", WSAGetLastError());

            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
        }

        addr = addr->ai_next;
    }
    while (addr != NULL);

    freeaddrinfo(servinfo);

    if (ConnectSocket == INVALID_SOCKET)
        printf("unable to connect to server\n");
}

On the server side:

  1. you are not doing any error handling on socket(), bind() or listen().
  2. SO_REUSEADDR has to be enabled before calling bind(), not after. And you are not even enabling it correctly, either.
  3. you are not freeing the memory that getaddrinfo() returns.

Try this instead:

int _tmain(int argc, _TCHAR* argv[])
{
    // WINDOWS SETUP
    WSAData wsaData;
    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) 
    {
        fprintf(stderr, "WSAStartup failed.\n");
        exit(1);
    }

    // PREPARE TO LAUNCH
    int status;
    struct sockaddr_storage their_addr;
    socklen_t addr_size;
    SOCKET client;

    struct addrinfo hints = {0};
    struct addrinfo *servinfo;  // will point to the results

    hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
    hints.ai_flags = AI_PASSIVE;     // fill in my IP for me
    //hints.ai_flags |= AI_NUMERICSERV; // parse a port number (not supported on Windows)

    status = getaddrinfo(NULL, "80", &hints, &servinfo);
    if (status != 0) 
    {
        fprintf(stderr, "getaddrinfo error: (%d) %s\n", status, gai_strerror(status));
        getchar();
        exit(1);
    }

    // optional, loop through servinfo creating a separate
    // listening socket for each address reported...

    // GET THE FILE DESCRIPTOR  
    SOCKET mSocket = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);
    if (mSocket == INVALID_SOCKET)
    {
        fprintf(stderr, "socket error: %d\n", WSAGetLastError());
        freeaddrinfo(servinfo);
        closesocket(mSocket);
        getchar();
        exit(1);
    }

    // lose the pesky "Address already in use" error message
    BOOL yes = TRUE;
    if (setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)) == SOCKET_ERROR)
    {
        fprintf(stderr, "setsockopt error: %d\n", WSAGetLastError());
        freeaddrinfo(servinfo);
        closesocket(mSocket);
        getchar();
        exit(1);
    }

    // WHAT PORT AM I ON
    if (bind(mSocket, servinfo->ai_addr, servinfo->ai_addrlen) == SOCKET_ERROR)
    {
        fprintf(stderr, "bind error: %d\n", WSAGetLastError());
        freeaddrinfo(servinfo);
        closesocket(mSocket);
        getchar();
        exit(1);
    }

    freeaddrinfo(servinfo);

    int backlog = 2;
    if (listen(mSocket, backlog) == SOCKET_ERROR)
    {
        fprintf(stderr, "listen error: %d\n", WSAGetLastError());
        closesocket(mSocket);
        getchar();
        exit(1);
    }

    // SERVER STARTED LISTENING SUCCESFULLY
    printf("Server is listening...\n");

    // ACCEPT
    addr_size = sizeof their_addr;
    client = accept(mSocket, (struct sockaddr*)&their_addr, &addr_size);
    if (client == INVALID_SOCKET)
    {
        fprintf(stderr, "accept error: %d\n", WSAGetLastError());
    }
    else
    {
        char ip[NI_MAXHOST] = {0};
        char port[NI_MAXSERV] = {0};

        status = getnameinfo((struct sockaddr*)&their_addr, addr_size, ip, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
        if (status == 0)
            printf("Client connected from %s:%s\n", ip, port);
        else
            printf("Client connected. getnameinfo error: (%d) %s\n", status, gai_strerror(status));

        //...

        closesocket(client);
    }        

    closesocket(mSocket);
    printf("Server ended");

    getchar();

    return 0;
}

Upvotes: 4

Related Questions