tags:

views:

189

answers:

4

I've got an application using sockets (which I did not write, so bear with me) and when I try to close a socket, closesocket() fails with error WSAEOPNOTSUPP and the socket sticks around...as in, it is not fully deleted.

The socket is created as follows:

bool Socket::CreateConnection()
{
   int error;
   struct addrinfo hints;
   struct addrinfo *list = NULL;

   memset(&hints, 0, sizeof(hints));
   hints.ai_family = AF_INET;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_protocol = IPPROTO_TCP;

   error = getaddrinfo(socketAddress.c_str(), socketPort.c_str(), &hints, &list);
   if (error)
   {
      Log().RecordError("Unable to initialize connection to server", WSAGetLastError(), EventTypeError);
   }

   for (struct addrinfo *ptr = list; ptr != NULL; ptr = ptr->ai_next)
   {
      connection = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
      if (connection == INVALID_SOCKET)
      {
         Log().RecordError("Unable to initialize socket connection", WSAGetLastError(), EventTypeError);
         break;
      }

      error = connect(connection, ptr->ai_addr, (int)ptr->ai_addrlen);
      if (error == SOCKET_ERROR)
      {
         closesocket(connection);
         connection = INVALID_SOCKET;
         continue;
      }
      break;
   }

   freeaddrinfo(list);

   return connection != INVALID_SOCKET;
}

And the destructor for the class:

Socket::~Socket()
{
   int error;

   if (connection != INVALID_SOCKET)
   {
      continueReading = false;

      error = shutdown(connection, SD_SEND);
      if (error != SOCKET_ERROR)
      {
         /* Finish any necessary receives to politely close the socket */
         int length;
         do
         {
            char buffer[1024];
            length = recv(connection, buffer, sizeof(buffer)/sizeof(*buffer), MSG_WAITALL);
         } while (length > 0);
      }
      else
      {
         Log().RecordError("Error shutting down connection to server", WSAGetLastError(), EventTypeError);
      }

      closesocket(connection);  //Fails HERE
      int wsa_err = WSAGetLastError();
      if(wsa_err)
       Log().RecordError("closesocket() error", wsa_err, EventTypeError);
   }

   if (winsockInitialized)
   {
      WSACleanup();
   }
}

Anyone have a clue why this would happen??

+1  A: 

You're not checking the return code on closesocket(), which means that WSAGetLastError() may or may not be related to the closesocket operation.

17 of 26
A: 

I am not a Windows socket guru, but I will have a try still .. Are you sure that the code returned by WSAGetLastError() concern the call to closesocket() ?

Quoting msdn :

... This is necessary because some functions may reset the last extended error code to 0 if they succeed ...

I assume you may have a previous socket related call which fail(?). Msdn tells that after each socket related call , you must prevent that by calling WSASetLastError() with 0.

To specifically reset the extended error code, use the WSASetLastError function call with the iError parameter set to zero.

yves Baumes
A: 

The error status is almost certainly left over from a previous operation. Winsock functions do not normally clear the error status when they succeed.

Check the return code from closesocket(). If that does not indicate an error, then the value of WSAGetLastError() is meaningless.

Michael J
A: 

The error code is left over from recv as the flag MSG_WAITALL is not supported on windows xp

Lodle