When building the cURL library on Windows with _WIN32_WINNT=0x0600, cURL will
use the WSAPoll API function (available in Vista and higher).
However, cURL will suffer from a bug in WSAPoll.
When the cURL library is used to setup a connection to an incorrect port,
normally the result is CURLE_COULDNT_CONNECT, /* 7 */, but due to the bug in
WSAPoll, the result now is CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time
was reached */.
See for example
http://social.msdn.microsoft.com/Forums/hu/wsk/thread/18769abd-fca0-4d3c-9884-1a38ce27ae90
("WSAPoll and non-blocking connects to non-existent ports").
The bug in WSAPoll is also demonstrated in the attached program
TestSocketConnect.cpp.
Adapt lines 141 and 142 to specify IP address and port number. In my case:
TestSocketConnection("10.21.46.81", 443, lTimeout);
TestSocketConnection("10.21.46.81", 8443, lTimeout);
Port 443 is not available, port 8443 works fine.
Output of the program (specify timeout in ms on command line, default is 1000):
=============
Hello, world!
WSAStartup returned 0.
lSOCKET is 0x00000074.
ioctlsocket(FIONBIO, 1) returned 0.
connecting to 10.21.46.81, port 443.
connect() returned -1.
WSAGetLastError() returned 10035.
WSAPoll(timeout=1000ms) returned 0.
lWSAPOLLFD.revents is 0x00
getsockopt() returned 0, lError is 10061.
closesocket() returned 0.
lSOCKET is 0x00000074.
ioctlsocket(FIONBIO, 1) returned 0.
connecting to 10.21.46.81, port 8443.
connect() returned -1.
WSAGetLastError() returned 10035.
WSAPoll(timeout=1000ms) returned 1.
lWSAPOLLFD.revents is 0x10
getsockopt() returned 0, lError is 0.
closesocket() returned 0.
WSACleanup returned 0.
Bye, world!
=============
#include <stdio.h>
#include <WinSock2.h>
void TestSocketConnection(
const char * aIPAddress,
USHORT aPortNumber,
INT aTimeout
)
{
SOCKET lSOCKET = socket(
AF_INET, // 2, //
family
SOCK_STREAM, // 1, // type
IPPROTO_IP // 0 //
protocol
);
printf( "\n"
"\n"
"lSOCKET is 0x%08X.\n",
lSOCKET
);
unsigned long
lFlags = 1;
int lReturnValue = ioctlsocket(
lSOCKET,
FIONBIO,
&lFlags
);
printf( "ioctlsocket(FIONBIO, 1) returned %d.\n",
lReturnValue
);
printf( "connecting to %s, port %u.\n",
aIPAddress,
aPortNumber
);
sockaddr_in lsockaddr_in;
lsockaddr_in.sin_family = AF_INET;
lsockaddr_in.sin_addr.s_addr = inet_addr(aIPAddress);
lsockaddr_in.sin_port = htons(aPortNumber);
lReturnValue = connect(
lSOCKET,
(sockaddr *)&lsockaddr_in,
sizeof(lsockaddr_in)
);
printf( "connect() returned %d.\n",
lReturnValue
);
int lWSAError = 0;
if (lReturnValue == SOCKET_ERROR) {
lWSAError = WSAGetLastError();
printf( "WSAGetLastError() returned %d.\n",
lWSAError
);
}
if (lWSAError == WSAEWOULDBLOCK) {
int lError = 0;
int lErrorSize = sizeof(lError);
int lPollCount = 0;
while (lPollCount == 0 && lError == 0) {
WSAPOLLFD lWSAPOLLFD;
lWSAPOLLFD.fd = lSOCKET;
lWSAPOLLFD.events = POLLWRNORM;
lWSAPOLLFD.revents = 0;
lPollCount = WSAPoll(
&lWSAPOLLFD,
1,
aTimeout
);
printf( "\n"
"WSAPoll(timeout=%dms) returned %d.\n"
"lWSAPOLLFD.revents is 0x%02X\n",
aTimeout,
lPollCount,
lWSAPOLLFD.revents
);
lReturnValue = getsockopt(
lSOCKET,
SOL_SOCKET,
SO_ERROR,
(char *)&lError,
&lErrorSize
);
printf( "getsockopt() returned %d, lError is %d.\n",
lReturnValue,
lError
);
}
}
lReturnValue = closesocket(lSOCKET);
printf( "\n"
"closesocket() returned %d.\n",
lReturnValue
);
}
int main(
int aArgumentCount,
char * aArgumentValue[]
)
{
printf("Hello, world!\n");
WORD lRequestedVersion = MAKEWORD(2, 2);
WSADATA lWSADATA;
int lReturnValue = WSAStartup(
lRequestedVersion,
&lWSADATA
);
printf( "WSAStartup returned %d.\n",
lReturnValue
);
INT lTimeout = 1000;
if (2 <= aArgumentCount) {
lTimeout = atoi(aArgumentValue[1]);
}
TestSocketConnection("10.21.46.81", 443, lTimeout);
TestSocketConnection("10.21.46.81", 8443, lTimeout);
lReturnValue = WSACleanup();
printf( "\n"
"WSACleanup returned %d.\n",
lReturnValue
);
printf("Bye, world!\n");
return 0;
}
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html