简体   繁体   中英

Winsock2 select() returns WSAEINVAL (error 10022)

I have the given code:

#include <winsock2.h>
#include <sys/time.h>
#include <iostream>

int main()
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        std::cout << "WSA Initialization failed!" << std::endl;
        WSACleanup();
    }

    timeval time;
    time.tv_sec = 1;
    time.tv_usec = 0;
    int retval = select(0, NULL, NULL, NULL, &time);
    if (retval == SOCKET_ERROR)
    {
        std::cout << WSAGetLastError() << std::endl;
    }

    return 0;
}

It prints 10022 , which means error WSAEINVAL. According to this page , I can get this error only if:

WSAEINVAL: The time-out value is not valid, or all three descriptor parameters were null.

However, I have seen a few examples calling select() without any FD_SET s. Is it possible somehow? I need to do it in a client-side code to let the program sleep for short periods while it is not connected to the server.

From the notorious and offensive Winsock 'lame list' :

Calling select() with three empty FD_SETs and a valid TIMEOUT structure as a sleezy delay function.

Inexcusably lame.

Note the mis-spelling. The document is worth reading, if you can stand it, just to see the incredible depths hubris can attain. In case they've recanted, or discovered that they didn't invent the Sockets API, you could try it with empty FD sets instead of null parameters, but I don't hold out much hope.

However, I have seen a few examples calling select() without any FD_SETs.

It will work in most OS's (that aren't Windows).

Is it possible somehow [under Windows]?

Not directly, but it's easy enough to roll your own wrapper around select() that gives you the behavior you want even under Windows:

int proper_select(int largestFileDescriptorValuePlusOne, struct fd_set * readFS, struct fd_set * writeFS, struct fd_set * exceptFS, struct timeVal * timeout)
{
#ifdef _WIN32
   // Note that you *do* need to pass in the correct value 
   // for (largestFileDescriptorValuePlusOne) for this wrapper
   // to work; Windows programmers sometimes just pass in a dummy value, 
   // because the current Windows implementation of select() ignores the 
   // parameter, but that's a portability-killing hack and wrong, 
   // so don't do it!
   if ((largestFileDescriptorValuePlusOne <= 0)&&(timeout != NULL))
   {
      // Windows select() will error out on a timeout-only call, so call Sleep() instead.
      Sleep(((timeout->tv_sec*1000000)+timeout->tv_usec)/1000);
      return 0;
   }
#endif

   // in all other cases we just pass through to the normal select() call
   return select(maxFD, readFS, writeFS, exceptFS, timeout);
}

... then just call proper_select() instead of select() and you're golden.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM