Winsock2 select() returns WSAEINVAL(错误 10022)
Winsock2 select() returns WSAEINVAL (error 10022)
我有给定的代码:
#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;
}
它打印10022
,这意味着错误WSAEINVAL。根据 this page,只有在以下情况下我才会收到此错误:
WSAEINVAL: The time-out value is not valid, or all three descriptor parameters were null.
但是,我看到一些调用 select() 时没有任何 FD_SET
的示例。有可能吗?我需要在客户端代码中执行此操作,让程序在未连接到服务器时短时间休眠。
来自臭名昭著的冒犯Winsock 'lame list':
Calling select() with three empty FD_SETs and a valid TIMEOUT structure as a sleezy delay function.
Inexcusably lame.
注意拼写错误。该文件值得一读,如果你能忍受的话,只是为了看看狂妄自大可以达到令人难以置信的深度。万一他们放弃了,或者发现套接字不是他们发明的API,您可以尝试使用空 FD 集而不是空参数,但我不抱太大希望。
However, I have seen a few examples calling select() without any
FD_SETs.
它适用于大多数 OS(不是 Windows)。
Is it possible somehow [under Windows]?
不是直接的,但是很容易围绕 select() 滚动您自己的包装器,即使在 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);
}
...然后只需调用 proper_select() 而不是 select() 就可以了。
我有给定的代码:
#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;
}
它打印10022
,这意味着错误WSAEINVAL。根据 this page,只有在以下情况下我才会收到此错误:
WSAEINVAL: The time-out value is not valid, or all three descriptor parameters were null.
但是,我看到一些调用 select() 时没有任何 FD_SET
的示例。有可能吗?我需要在客户端代码中执行此操作,让程序在未连接到服务器时短时间休眠。
来自臭名昭著的冒犯Winsock 'lame list':
Calling select() with three empty FD_SETs and a valid TIMEOUT structure as a sleezy delay function.
Inexcusably lame.
注意拼写错误。该文件值得一读,如果你能忍受的话,只是为了看看狂妄自大可以达到令人难以置信的深度。万一他们放弃了,或者发现套接字不是他们发明的API,您可以尝试使用空 FD 集而不是空参数,但我不抱太大希望。
However, I have seen a few examples calling select() without any FD_SETs.
它适用于大多数 OS(不是 Windows)。
Is it possible somehow [under Windows]?
不是直接的,但是很容易围绕 select() 滚动您自己的包装器,即使在 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);
}
...然后只需调用 proper_select() 而不是 select() 就可以了。