Socket Connection problem in Windows XP System from VC++
-
I am using the following function to find out whether I can connect to a particular IP address(for ex:3.205.202.6 etc...) in VC++. This function returns TRUE on Windows 2000 if the given IP address is communicating one. But on Windows XP system it always returns FALSE (However I can still say ping to this IP :- 3.205.202.6 from DOS command prompt. It replies correctly). Can anyone please help me to root cause this issue in Windows XP system. Is this socket API not valid on Win XP system? On Win2000, it always gives me the correct status. BOOL IsOnline(const CString &strIPAddr) { SOCKET tmpSocket; struct sockaddr_in SClient; u_long argp; fd_set stReadFDS; fd_set stWriteFDS; fd_set stExceptFDS; struct timeval stTimeOut; int nSelectReturn; DWORD nTicks; DWORD nTickStart; //create a socket tmpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ; if (tmpSocket == INVALID_SOCKET) { return FALSE; } // make the socket non blocking argp = 1L; // non zero enables nonblocking mode if (ioctlsocket(tmpSocket, FIONBIO, (u_long FAR *) &argp) == SOCKET_ERROR) { closesocket(tmpSocket); return FALSE; } // connect to the given IP address SClient.sin_family = AF_INET; SClient.sin_port = htons(502); SClient.sin_addr.s_addr = inet_addr(strIPAddr); int nLastErr; if (connect(tmpSocket, (sockaddr *) &SClient, sizeof(sockaddr_in)) == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEWOULDBLOCK) { closesocket(tmpSocket); return FALSE; } nTicks = 500; nTickStart = GetTickCount(); nSelectReturn = SOCKET_ERROR; int ic = 0; while (nSelectReturn <= 0 && (GetTickCount() - nTickStart) < nTicks) { // clear all sockets from FDS structure, then put our socket into the socket descripter FD_ZERO(&stReadFDS); FD_ZERO(&stWriteFDS); FD_ZERO(&stExceptFDS); FD_SET(tmpSocket, &stReadFDS); FD_SET(tmpSocket, &stWriteFDS); FD_SET(tmpSocket, &stExceptFDS); // set a timeout of 1 second stTimeOut.tv_sec = 1; stTimeOut.tv_usec = 0; nSelectReturn = select(-1, &stReadFDS, &stWriteFDS, &stExceptFDS, &stTimeOut); if (nSelectReturn == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEINPROGRESS) { closesocket(tmpSocket); return FALSE; } } } if (nSelectReturn <= 0 || stWriteFDS.fd_count == 0) { closesocket(tmpSocket); return FALSE; } } close
-
I am using the following function to find out whether I can connect to a particular IP address(for ex:3.205.202.6 etc...) in VC++. This function returns TRUE on Windows 2000 if the given IP address is communicating one. But on Windows XP system it always returns FALSE (However I can still say ping to this IP :- 3.205.202.6 from DOS command prompt. It replies correctly). Can anyone please help me to root cause this issue in Windows XP system. Is this socket API not valid on Win XP system? On Win2000, it always gives me the correct status. BOOL IsOnline(const CString &strIPAddr) { SOCKET tmpSocket; struct sockaddr_in SClient; u_long argp; fd_set stReadFDS; fd_set stWriteFDS; fd_set stExceptFDS; struct timeval stTimeOut; int nSelectReturn; DWORD nTicks; DWORD nTickStart; //create a socket tmpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ; if (tmpSocket == INVALID_SOCKET) { return FALSE; } // make the socket non blocking argp = 1L; // non zero enables nonblocking mode if (ioctlsocket(tmpSocket, FIONBIO, (u_long FAR *) &argp) == SOCKET_ERROR) { closesocket(tmpSocket); return FALSE; } // connect to the given IP address SClient.sin_family = AF_INET; SClient.sin_port = htons(502); SClient.sin_addr.s_addr = inet_addr(strIPAddr); int nLastErr; if (connect(tmpSocket, (sockaddr *) &SClient, sizeof(sockaddr_in)) == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEWOULDBLOCK) { closesocket(tmpSocket); return FALSE; } nTicks = 500; nTickStart = GetTickCount(); nSelectReturn = SOCKET_ERROR; int ic = 0; while (nSelectReturn <= 0 && (GetTickCount() - nTickStart) < nTicks) { // clear all sockets from FDS structure, then put our socket into the socket descripter FD_ZERO(&stReadFDS); FD_ZERO(&stWriteFDS); FD_ZERO(&stExceptFDS); FD_SET(tmpSocket, &stReadFDS); FD_SET(tmpSocket, &stWriteFDS); FD_SET(tmpSocket, &stExceptFDS); // set a timeout of 1 second stTimeOut.tv_sec = 1; stTimeOut.tv_usec = 0; nSelectReturn = select(-1, &stReadFDS, &stWriteFDS, &stExceptFDS, &stTimeOut); if (nSelectReturn == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEINPROGRESS) { closesocket(tmpSocket); return FALSE; } } } if (nSelectReturn <= 0 || stWriteFDS.fd_count == 0) { closesocket(tmpSocket); return FALSE; } } close
-
I am using the following function to find out whether I can connect to a particular IP address(for ex:3.205.202.6 etc...) in VC++. This function returns TRUE on Windows 2000 if the given IP address is communicating one. But on Windows XP system it always returns FALSE (However I can still say ping to this IP :- 3.205.202.6 from DOS command prompt. It replies correctly). Can anyone please help me to root cause this issue in Windows XP system. Is this socket API not valid on Win XP system? On Win2000, it always gives me the correct status. BOOL IsOnline(const CString &strIPAddr) { SOCKET tmpSocket; struct sockaddr_in SClient; u_long argp; fd_set stReadFDS; fd_set stWriteFDS; fd_set stExceptFDS; struct timeval stTimeOut; int nSelectReturn; DWORD nTicks; DWORD nTickStart; //create a socket tmpSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ; if (tmpSocket == INVALID_SOCKET) { return FALSE; } // make the socket non blocking argp = 1L; // non zero enables nonblocking mode if (ioctlsocket(tmpSocket, FIONBIO, (u_long FAR *) &argp) == SOCKET_ERROR) { closesocket(tmpSocket); return FALSE; } // connect to the given IP address SClient.sin_family = AF_INET; SClient.sin_port = htons(502); SClient.sin_addr.s_addr = inet_addr(strIPAddr); int nLastErr; if (connect(tmpSocket, (sockaddr *) &SClient, sizeof(sockaddr_in)) == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEWOULDBLOCK) { closesocket(tmpSocket); return FALSE; } nTicks = 500; nTickStart = GetTickCount(); nSelectReturn = SOCKET_ERROR; int ic = 0; while (nSelectReturn <= 0 && (GetTickCount() - nTickStart) < nTicks) { // clear all sockets from FDS structure, then put our socket into the socket descripter FD_ZERO(&stReadFDS); FD_ZERO(&stWriteFDS); FD_ZERO(&stExceptFDS); FD_SET(tmpSocket, &stReadFDS); FD_SET(tmpSocket, &stWriteFDS); FD_SET(tmpSocket, &stExceptFDS); // set a timeout of 1 second stTimeOut.tv_sec = 1; stTimeOut.tv_usec = 0; nSelectReturn = select(-1, &stReadFDS, &stWriteFDS, &stExceptFDS, &stTimeOut); if (nSelectReturn == SOCKET_ERROR) { nLastErr = WSAGetLastError(); if (nLastErr != WSAEINPROGRESS) { closesocket(tmpSocket); return FALSE; } } } if (nSelectReturn <= 0 || stWriteFDS.fd_count == 0) { closesocket(tmpSocket); return FALSE; } } close
The only thing I see right away is that your timeout value is pretty short. Half a second... Factor in the accuracy of clock ticks and it often could be much shorter. For what it's worth, here's an alternative method using an event instead of looping (which is inefficient use of CPU!)...
tmpSocket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) ;
if (tmpSocket != INVALID_SOCKET)
{
BOOL fConnectSuccess = FALSE;HANDLE hNetEvent = ::CreateEvent(NULL, true, false, NULL); // manual reset
::WSAEventSelect(tmpSocket, hNetEvent, FD_CONNECT);
// Socket is now NON-blocking
sockaddr_in SClient;
SClient.sin_family = AF_INET;
SClient.sin_port = htons(502);
SClient.sin_addr.s_addr = inet_addr(strIPAddr);// Attempt to Connect - timeout 10 seconds
if (SOCKET_ERROR == ::connect(tmpSocket, (sockaddr *) &SClient, sizeof(sockaddr_in)))
{
int rc = WSAGetLastError();
if (rc == WSAEWOULDBLOCK)
{
if (WAIT_OBJECT_0 == ::WaitForSingleObject(hNetEvent, 10000))
{
WSANETWORKEVENTS WsaNetworkEvents;
if (0 == ::WSAEnumNetworkEvents(tmpSocket, hNetEvent, &WsaNetworkEvents)) //(resets hNetEvent)
{
if (0 != WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT])
{
// connect error occurred
}
else
{
// connect success!
fConnectSuccess = TRUE;
}
}
}
else
{
// timed out
}
}
else
{
//::connect() failed
}
}
else
{
// connect success!
fConnectSuccess = TRUE;
}::closesocket(tmpSocket);
::CloseHandle(hNetEvent);return fConnectSuccess;
}
else
{
return FALSE;
}-- modified at 13:42 Wednesday 23rd May, 2007 added cleanup for event handle :rolleyes:
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder