WSA error 10048 when binding server sockets

10,011

WSA 10048 is the 'Address in use' error (https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx).

I don't have windows so I can't run your code, but this error commonly occurs when a server keeps a server port reserved for a number of minutes before it can be reused.

A socket option is provided to allow faster reuse, setsockopt (SO_REUSEADDR).

In your case, you would add the following lines right after creating and checking ListenSocket:

int optval = 1;
iResult = ::setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);

if (iResult == SOCKET_ERROR) {
        std::cout << 9 << std::endl;
        printf("setsockopt failed with error: %d\n", WSAGetLastError());
}

The TCP stack has good reasons for not re-issuing old port numbers immediatly after they are released, but for server ports this is unwanted behaviour. Only, the stack does not know the difference between a server and a non-server port, so we must use setsockopt.

Share:
10,011
mindoo
Author by

mindoo

Updated on June 04, 2022

Comments

  • mindoo
    mindoo almost 2 years

    I started with the simple server tutorial on the msdn website in order to learn how to use sockets in client and server applications.

    Once I was done following thet tutorial, I started adapting the client and server code into multithreaded proggrams in order to make a tchat client and server. Everything was going very well until I ran into WSA error 10048. I tried using different ports for each socket but it still did not solve the error.

    Here is my server code :

    #undef UNICODE
    
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <thread>
    #include <vector>
    
    // Need to link with Ws2_32.lib
    #pragma comment (lib, "Ws2_32.lib")
    // #pragma comment (lib, "Mswsock.lib")
    
    //Global values
    //I put them as global values in order to get the server up and running.
    //I will try to pass them as params later on
    int iResult;
    struct addrinfo *result = NULL;
    struct addrinfo hints;
    int numClients = 0;
    SOCKET ClientSocket[5];
    std::thread** sendReceiveThread = new std::thread*[5];
    
    //Prototypes
    int listen(SOCKET ListenSocket);
    int accept(SOCKET ListenSocket);
    int sendReceive();
    int shutdownFunction(SOCKET ClientSocket);
    
    #define DEFAULT_BUFLEN 512
    #define DEFAULT_PORT1 "1016"
    #define DEFAULT_PORT2 "1017"
    #define DEFAULT_PORT3 "1018"
    #define DEFAULT_PORT4 "1019"
    #define DEFAULT_PORT5 "1020"
    
    int main()
    {
        std::cout << 1 << std::endl;
        WSADATA wsaData;
    
        SOCKET ListenSocket = INVALID_SOCKET;
    
    
        // Initialize Winsock
        std::cout << 2 << std::endl;
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != 0) {
            std::cout << 3 << std::endl;
            printf("WSAStartup failed with error: %d\n", iResult);
            return 1;
        }
    
        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
    
        std::thread ListenThread{ [ListenSocket](){listen(ListenSocket); } };
        ListenThread.join();
    
        return 0;
    }
    
    int listen(SOCKET ListenSocket)
    {
        int numPort = 1;
        std::vector<std::thread*> thread_vec;
        while (true)
        {
            if (numPort == 1)
            {
                // Resolve the server address and port
                std::cout << 4 << std::endl;
                iResult = getaddrinfo(NULL, DEFAULT_PORT1, &hints, &result);
                numPort++;
                if (iResult != 0) {
                    std::cout << 5 << std::endl;
                    printf("getaddrinfo failed with error: %d\n", iResult);
                    WSACleanup();
                    break;
                }
            }
    
            else if (numPort == 2)
            {
                // Resolve the server address and port
                std::cout << 4 << std::endl;
                iResult = getaddrinfo(NULL, DEFAULT_PORT2, &hints, &result);
                numPort++;
                if (iResult != 0) {
                    std::cout << 5 << std::endl;
                    printf("getaddrinfo failed with error: %d\n", iResult);
                    WSACleanup();
                    break;
                }
            }
    
            else if (numPort == 3)
            {
                // Resolve the server address and port
                std::cout << 4 << std::endl;
                iResult = getaddrinfo(NULL, DEFAULT_PORT3, &hints, &result);
                numPort++;
                if (iResult != 0) {
                    std::cout << 5 << std::endl;
                    printf("getaddrinfo failed with error: %d\n", iResult);
                    WSACleanup();
                    break;
                }
            }
    
            else if (numPort == 4)
            {
                // Resolve the server address and port
                std::cout << 4 << std::endl;
                iResult = getaddrinfo(NULL, DEFAULT_PORT4, &hints, &result);
                numPort++;
                if (iResult != 0) {
                    std::cout << 5 << std::endl;
                    printf("getaddrinfo failed with error: %d\n", iResult);
                    WSACleanup();
                    break;
                }
            }
    
            else if (numPort == 5)
            {
                // Resolve the server address and port
                std::cout << 4 << std::endl;
                iResult = getaddrinfo(NULL, DEFAULT_PORT5, &hints, &result);
                numPort++;
                if (iResult != 0) {
                    std::cout << 5 << std::endl;
                    printf("getaddrinfo failed with error: %d\n", iResult);
                    WSACleanup();
                    break;
                }
            }
    
            // Create a SOCKET for connecting to server
            std::cout << 6 << std::endl;
            ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
            if (ListenSocket == INVALID_SOCKET) {
                std::cout << 7 << std::endl;
                printf("socket failed with error: %ld\n", WSAGetLastError());
                freeaddrinfo(result);
                WSACleanup();
                break;
            }
    
            // Setup the TCP listening socket
            std::cout << 8 << std::endl;
            iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
            if (iResult == SOCKET_ERROR) {
                std::cout << 9 << std::endl;
                printf("bind failed with error: %d\n", WSAGetLastError());
                freeaddrinfo(result);
                closesocket(ListenSocket);
                WSACleanup();
                break;
            }
    
            freeaddrinfo(result);
    
            std::cout << 10 << std::endl;
            iResult = listen(ListenSocket, SOMAXCONN);
            if (iResult == SOCKET_ERROR) {
                std::cout << 11 << std::endl;
                printf("listen failed with error: %d\n", WSAGetLastError());
                closesocket(ListenSocket);
                WSACleanup();
                break;
            }
    
    
            static std::thread AcceptThread{ [ListenSocket](){accept(ListenSocket); } };
            thread_vec.push_back(&AcceptThread);
        }
        for (auto it : thread_vec) it->join();
        return 0;
    }
    
    int accept(SOCKET ListenSocket)
    {
        numClients++;
        const int currentNumClients = numClients;
        for (int i = 0; i <= 5; i++)
        {
            ClientSocket[i] = INVALID_SOCKET;
        }
    
        // Accept a client socket
        std::cout << 12 << std::endl;
    
        std::cout << 13 << std::endl;
    
        ClientSocket[currentNumClients] = accept(ListenSocket, NULL, NULL);
        if (ClientSocket[currentNumClients] == INVALID_SOCKET)
        {
            printf("accept failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
    
        sendReceiveThread[currentNumClients] = new std::thread([](){sendReceive(); });
        (*sendReceiveThread[currentNumClients]).join();
        delete sendReceiveThread[currentNumClients];
    
        return 0;
    }
    
    int sendReceive()
    {
        int currentNumClients = numClients;
        int iSendResult;
        char recvbuf[DEFAULT_BUFLEN];
        int recvbuflen = DEFAULT_BUFLEN;
    
        // Receive until the peer shuts down the connection
        while(true)
        {
            std::cout << 14 << std::endl;
            iResult = recv(ClientSocket[currentNumClients], recvbuf, recvbuflen, 0);
            std::cout << iResult << std::endl;
            if (iResult > 0) {
                std::cout << 15 << std::endl;
                printf("Bytes received: %d\n", iResult);
    
                // Echo the buffer back to the clients
                std::cout << 16 << std::endl;
                for (int i = 1; i <= numClients; i++)
                {
                    iSendResult = send(ClientSocket[currentNumClients], recvbuf, iResult, 0);
                    if (iSendResult == SOCKET_ERROR) {
                        std::cout << 17 << std::endl;
                        printf("send failed with error: %d\n", WSAGetLastError());
                        closesocket(ClientSocket[currentNumClients]);
                        WSACleanup();
                        return 1;
                    }
                    printf("Bytes sent: %d\n", iSendResult);
                }
            }
            else if (iResult == 0) {
                std::cout << 18 << std::endl;
                printf("Connection closing...\n");
                break;
            }
            else {
                std::cout << 19 << std::endl;
                printf("recv failed with error: %d\n", WSAGetLastError());
                std::cout << "On client #" << currentNumClients << std::endl;
                break;
            }
    
        }
    
        iResult = shutdownFunction(ClientSocket[currentNumClients]);
    
        std::cout << 22 << std::endl;
        // cleanup
        closesocket(ClientSocket[currentNumClients]);
        WSACleanup();
    
        return 0;
    }
    
    int shutdownFunction(SOCKET ClientSocket)
    {
        std::cout << 20 << std::endl;
        iResult = shutdown(ClientSocket, SD_SEND);
        if (iResult == SOCKET_ERROR) {
            std::cout << 21 << std::endl;
            printf("shutdown failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
    
        return 0;
    }
    

    You might notice the different couts, those are just couts to know how the proggram behaves.

  • mindoo
    mindoo over 8 years
    I had done some research and I found the same link as you and the same setsockopt function but I dont understand what it really does and how I would implement it in my code.
  • EvertW
    EvertW over 8 years
    I have expanded the answer.
  • mindoo
    mindoo over 8 years
    I tried putting the piece of code you specified in your answer at the line 156 but it tells me : Error 1 error C2664: 'int setsockopt(SOCKET,int,int,const char *,int)' : cannot convert argument 4 from 'int *' to 'const char *'
  • mindoo
    mindoo over 8 years
    @dbush thanks, that was a quick and easy fix but now my code just crashes, would you have any idea of why it crashes.
  • EvertW
    EvertW over 8 years
    Can you find out at which line it crashes? E.g. by running the code in the debugger?
  • mindoo
    mindoo over 8 years
    @EvertW What I mean when I say it crashes is that it compiles fine but when I run it it says that the proggram has stopped working.
  • EvertW
    EvertW over 8 years
    I got that, that's what we have debuggers for ;-) If you are using visual studio (express), you should go through some tutorial, e.g. youtube.com/watch?v=eEJ5xKO7c3o . I found that through google by looking for "visual studio debugging tutorial".
  • mindoo
    mindoo over 8 years
    Oh ok, I'll definitly checkout that. I never used the debugger in VS apart from when I have just plain old errors (I'm not even sure that that is the debugger)
  • mindoo
    mindoo over 8 years
    @EvertW I followed the tutorial you suggested and then I went through each line and at line 65 (where I says ListenThread.join() ) it says that my proggram has triggered a break point. If I try to hit continue, it says : Unhandled exception at 0x77B95904 (ntdll.dll) in ConsoleApplication1.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77BB1378).
  • EvertW
    EvertW over 8 years
    This tells you two things: 1). The bug is located in another thread. You can debug threads after putting a breakpoint at their first line. 2). The error probably has something to do with memory mis-management.
  • EvertW
    EvertW over 8 years
    At the moment you do not need threads. When you create a thread and then immediatly join it, you might as well call a function directly. Is much easier to debug...
  • mindoo
    mindoo over 8 years
    @EvertW I think I'll try to just call the function directly without using a thread. And then if it doesn't work, then I'll try to go debug in the function.
  • mindoo
    mindoo over 8 years
    @EvertW So basically what I do is call the listen function directly without using a thread. I then added a if statement in order to break out of the loop when numPort is equal to 6 because that was what made my code crash. Now when I launch the server, what happens is that the server does all the setup code perfectly but when I try to connect to it with the client, on the server it says recv failed on client #1 with error 10054 and in the client, it says unable to connect to the server.
  • Jérôme Gillard
    Jérôme Gillard about 8 years
    Correct use would be: int flag = 1; setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&flag, sizeof(flag));