Reputation: 585
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.
Upvotes: 3
Views: 5457
Reputation: 311050
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().
Upvotes: 2
Reputation: 585
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
Upvotes: 1