3

SOLVED

The error was assuming that UDP and TCP have same structure of connection and initialization. Here I get more information about it:

http://bit.kuas.edu.tw/~csshieh/teach/np/winsock/

Hope it helps to everyone in my situation

Question

Im trying to code a library that uses UDP socket. Previously I used TCP IP socket and I wrote them successfully, afterward I decided to templatize these one to generalize it.

To make secure the templatization I created a enum

enum eSocketType { eTCP = SOCK_STREAM, eUDP = SOCK_DGRAM };

Socket are created with a static member on socket class that is templatized and receive that kind of enum.

Templated socket works with eTCP. But when I used eDCP the bind process fail and I get the error 10045 that means that "The operation is not supported" as sais in MSDN support

The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation is trying to accept a connection on a datagram socket.

SIMPLIFIED POST

Here is the summarize of the initialization code (It's the initialization proccess of the class that I described before editing the post (That is after "OLD POST" subsection)):

    int iResult = getaddrinfo(NULL, mPort.c_str(), &mHints, &mResult);
    if ( iResult != 0 ) {
        exit(-1);
    }
    mSocketOwn = socket(mResult->ai_family, mResult->ai_socktype, mResult->ai_protocol);
    if (mSocketOwn == INVALID_SOCKET) {
        freeaddrinfo(mResult);
        exit(-1);
    }

    #ifdef __linux__
        int yes = 1;
        iResult = setsockopt(mSocketOwn, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
    #endif
    #ifdef _WIN32
        bool bOptVal = TRUE;
        int bOptLen = sizeof(bool);
        iResult = setsockopt(mSocketOwn, SOL_SOCKET, SO_REUSEADDR, (char *) bOptVal, bOptLen);
    #endif

    iResult = bind( mSocketOwn, mResult->ai_addr, mResult->ai_addrlen); // <-- Here fails
    if (iResult == SOCKET_ERROR) {
        // Here I get the error 10045 if a read the last error
        closeSocket();
        exit(-1);

    }
    freeaddrinfo(mResult);

OLD POST

Before copy/pasting the code here is the structure:

There is a Socket class that has virtual members and protected constructor. This class also has the static members that create ServerSocket and ClientSocket classes respectively. The static members have the fist level of template with the previous enum. ServerSocket and ClientSocket inherite from Socket and are templatized (because the initialization depend on that template). Hope this intro make the code more understandable... Here we go:

Socket interface:

class Socket{
        public:
            int sendData(std::string _data);
            std::string receiveData();

        protected:      
            Socket()    {};
            virtual int initializeSocket() = 0;
            virtual int connectSocket() = 0;

            virtual int closeSocket() = 0;

            int getLastError();

        public:     // static members: Factory, etc
            template<eSocketType type_>
            static ClientSocket<type_>* createClientSocket(std::string _ip, std::string _port);

            template<eSocketType type_>
            static ServerSocket<type_>* createServerSocket(std::string _port);

        protected:  
            #if defined(_WIN32)
                WSADATA mWsaData;
            #endif

            SOCKET mSocketOut;

            addrinfo *mResult, mHints;
        };  //  class Socket

ServerSocket Interface:

template

class ServerSocket: public Socket{
        public:
            ServerSocket(const std::string _port);

            int listenClient();
            SOCKET acceptClient();

        protected:
            int initializeSocket();
            int connectSocket();

            int closeSocket();

        private:
            SOCKET mSocketOwn;

            std::string mPort;
        };  //  class ServerSocket

I omitted the client because the error start creating the server. Basically the ServerSocket constructor call both method InitiallizeSocket and ConnectSocket that are here:

template<eSocketType type_>
int ServerSocket<type_>::initializeSocket(){
    // Resolve the server address and port
    std::cout << "Getting address info";
    int iResult = getaddrinfo(NULL, mPort.c_str(), &mHints, &mResult);
    if ( iResult != 0 ) {
        std::cout << "getaddrinfo failed with error: " << iResult << std::endl;
        #if defined (_WIN32)
            WSACleanup();
        #endif
        return 1;
    }
    std::cout << "----> Got address info" << std::endl;

    // Create a SOCKET for connecting to server
    std::cout << "Creating server socket";
    mSocketOwn = socket(mResult->ai_family, mResult->ai_socktype, mResult->ai_protocol);
    if (mSocketOwn == INVALID_SOCKET) {
        std::cout << "Socket failed. Error was: " << getLastError() << std::endl;
        freeaddrinfo(mResult);
        return 1;
    }
    std::cout << "----> Socket created" << std::endl;

    return 0;
}
//-----------------------------------------------------------------------------
template<eSocketType type_>
int ServerSocket<type_>::connectSocket(){
    // Setup the TCP listening socket
    int iResult = 0;
    #ifdef __linux__
        int yes = 1;
        iResult = setsockopt(mSocketOwn, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
    #endif
    #ifdef _WIN32
        bool bOptVal = TRUE;
        int bOptLen = sizeof(bool);
        iResult = setsockopt(mSocketOwn, SOL_SOCKET, SO_REUSEADDR, (char *) bOptVal, bOptLen);
    #endif

    std::cout << "Binding to port";
    iResult = bind( mSocketOwn, mResult->ai_addr, mResult->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        std::cout << "Bind failed" << std::endl;
        std::cout << "Error was: " << getLastError() << std::endl;
        freeaddrinfo(mResult);
        closeSocket();
        return 1;
    }
    std::cout << "----> Binded to port" << std::endl;

    freeaddrinfo(mResult);
    return 0;

}

The socket is right initiallized but in the connectSocket method when it tries to bind it it fails and the 10045 error rises. As I said the TCP/IP socket work fine and no error rises. I read some tutorials about UDP socket but cant find any "missed step"... Does anyone know what is going on?

Thanks in advance, If more info is needed please tell me and I will add it. Pablo R.S.

Bardo91
  • 585
  • 2
  • 7
  • 17
  • 1
    you need to simplify this code right down to a small app that opens a UDP socket. Once that works then you can do all the fancy template stuff. Not sure why it needs to be templated but thats a different question – pm100 May 30 '14 at 22:10
  • Ok I'm going to edit it to simplify the code. The reason to templatize it is to define the socket in compile time no runtime (There's no other reason). – Bardo91 May 30 '14 at 22:13
  • 1
    dont edit to simplify. Make a simpler program with socket function call and bind function call hard coded with fixed params. – pm100 May 30 '14 at 22:16
  • mResult is only a errorFlag, it can be omitted inserting the functions inside the "if" sentences – Bardo91 May 30 '14 at 22:18
  • oh sorry, I confused mresult with iresult. mResult is an structure (http://msdn.microsoft.com/en-us/library/windows/desktop/ms737530(v=vs.85).aspx) that hold information about the host address. – Bardo91 May 30 '14 at 22:21
  • 1
    IMO, this puts a number of mostly-unrelated responsibilities into a single class. Although it's currently written more for client than server user, I showed what I think is a cleaner approach in [an answer on CR](http://codereview.stackexchange.com/a/46354/489) a while back. If I were in your shoes, I'd probably use something at least vaguely similar to that as a starting point. – Jerry Coffin May 30 '14 at 22:37
  • Think I've the solution... I assumed that TCP and UDP protocols have same life cycle but it seems that not: http://bit.kuas.edu.tw/~csshieh/teach/np/winsock/ Srry for the nuisance. I'm going to work on it! Thanks again for helping me – Bardo91 May 30 '14 at 22:43

2 Answers2

2

It seems more likely that you were calling listen() on the UDP socket and getting the error from that. I don't see anything in this code that would cause that error on bind().

user207421
  • 305,947
  • 44
  • 307
  • 483
1

The error was assuming that UDP and TCP have same structure of connection and initialization. Here I get more information about it:

http://bit.kuas.edu.tw/~csshieh/teach/np/winsock/

Hope it helps to everyone in my situation

Bardo91
  • 585
  • 2
  • 7
  • 17