S
Sergey V
Hi,
I'm trying to implement ping functionality via nonblocking sockets (as ICMP
protocol sometimes forbidden in firewalls).
Everything works correcly until some amount of pings performed - about 4000
(On WinXP SP2). Connection to valid hosts fails.
Restarting the application does not help. The procedure returns to work only
after some period - if application gets restarted in about 5 minutes.
Looking into TCPView from Sysinternal shows that plenty of open TCP
connection is active.
Runing on Win2000 server, aplication runs without the problems though plenty
of opened TCP connections connections listed too.
Is there way to force TCP connection to close right after the socket is
closed?
Sample code to reproduce:
// socket_ping.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "socket_ping.h"
#include <process.h>
#include <comdef.h>
#include <afxsock.h> // MFC socket extensions
#include <netmon.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
DWORD getHostIP(LPCTSTR pszHost, DWORD* pdwIP/* = NULL*/)
{
// resolve IP address
DWORD dwIP = 0;
HOSTENT* phe;
_bstr_t bsServer(pszHost);
if( pdwIP != NULL )
*pdwIP = 0;
dwIP = inet_addr(bsServer);
if( dwIP == INADDR_NONE ) // already an IP address ?
{
phe = gethostbyname(bsServer);
if( phe == NULL )
{
return 0;
}
dwIP = ((in_addr*)(phe->h_addr_list[0]))->S_un.S_addr;
}
if( pdwIP != NULL )
*pdwIP = dwIP;
return dwIP;
}
BOOL isHostAlive(LPCTSTR pszHost,
int iTimeout = 250,
USHORT uPort = PORT_NETBIOSSSN,
DWORD* pdwIP = NULL )
{
DWORD dwIP = getHostIP(pszHost, pdwIP);
if( dwIP == 0 )
return FALSE;
BOOL bIsAlive;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in tcpaddr = {AF_INET, htons(uPort)};
int error;
time_t start = time(NULL);
BOOL optTRUE = TRUE, optFALSE = FALSE;
time_t tStart = time(NULL);
tcpaddr.sin_addr.S_un.S_addr = dwIP;
ioctlsocket(s, FIONBIO, (ULONG*)&optTRUE);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optTRUE,
sizeof(optTRUE));
setsockopt(s, SOL_SOCKET, SO_DONTLINGER, (char*)&optTRUE,
sizeof(optTRUE));
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char*)&optFALSE,
sizeof(optFALSE));
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&optTRUE,
sizeof(optTRUE));
connect(s, (sockaddr*)&tcpaddr, sizeof(tcpaddr));
error = WSAGetLastError();
if( error == 0 || error == WSAEWOULDBLOCK )
{
fd_set fd_write = {1, s};
timeval twait = {0, iTimeout * 1000};
error = select(0, NULL, &fd_write, NULL, &twait);
error = WSAGetLastError();
bIsAlive = FD_ISSET(s, &fd_write);
}
else
{
bIsAlive = (error == WSAECONNREFUSED);
}
shutdown(s, 2 /*SD_BOTH*/);
closesocket(s);
static int n = 0;
printf(_T("%04d: isHostAlive(%s) = %d sec, alive = %d\r\n"),
++n, pszHost, time(NULL) - start, bIsAlive);
return bIsAlive;
}
long cThreads = 0;
static void thread(void* p)
{
for( int i = 1; i < 1000; i++ )
{
isHostAlive(_T("<hostnamehere>"));
}
InterlockedDecrement(&cThreads);
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit:GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
return 1;
}
AfxSocketInit();
for( int i = 0; i < 10; i++ )
{
_beginthread(thread, 0, NULL);
InterlockedIncrement(&cThreads);
}
while( cThreads > 0 )
Sleep(100);
return nRetCode;
}
I'm trying to implement ping functionality via nonblocking sockets (as ICMP
protocol sometimes forbidden in firewalls).
Everything works correcly until some amount of pings performed - about 4000
(On WinXP SP2). Connection to valid hosts fails.
Restarting the application does not help. The procedure returns to work only
after some period - if application gets restarted in about 5 minutes.
Looking into TCPView from Sysinternal shows that plenty of open TCP
connection is active.
Runing on Win2000 server, aplication runs without the problems though plenty
of opened TCP connections connections listed too.
Is there way to force TCP connection to close right after the socket is
closed?
Sample code to reproduce:
// socket_ping.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "socket_ping.h"
#include <process.h>
#include <comdef.h>
#include <afxsock.h> // MFC socket extensions
#include <netmon.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
DWORD getHostIP(LPCTSTR pszHost, DWORD* pdwIP/* = NULL*/)
{
// resolve IP address
DWORD dwIP = 0;
HOSTENT* phe;
_bstr_t bsServer(pszHost);
if( pdwIP != NULL )
*pdwIP = 0;
dwIP = inet_addr(bsServer);
if( dwIP == INADDR_NONE ) // already an IP address ?
{
phe = gethostbyname(bsServer);
if( phe == NULL )
{
return 0;
}
dwIP = ((in_addr*)(phe->h_addr_list[0]))->S_un.S_addr;
}
if( pdwIP != NULL )
*pdwIP = dwIP;
return dwIP;
}
BOOL isHostAlive(LPCTSTR pszHost,
int iTimeout = 250,
USHORT uPort = PORT_NETBIOSSSN,
DWORD* pdwIP = NULL )
{
DWORD dwIP = getHostIP(pszHost, pdwIP);
if( dwIP == 0 )
return FALSE;
BOOL bIsAlive;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in tcpaddr = {AF_INET, htons(uPort)};
int error;
time_t start = time(NULL);
BOOL optTRUE = TRUE, optFALSE = FALSE;
time_t tStart = time(NULL);
tcpaddr.sin_addr.S_un.S_addr = dwIP;
ioctlsocket(s, FIONBIO, (ULONG*)&optTRUE);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optTRUE,
sizeof(optTRUE));
setsockopt(s, SOL_SOCKET, SO_DONTLINGER, (char*)&optTRUE,
sizeof(optTRUE));
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char*)&optFALSE,
sizeof(optFALSE));
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&optTRUE,
sizeof(optTRUE));
connect(s, (sockaddr*)&tcpaddr, sizeof(tcpaddr));
error = WSAGetLastError();
if( error == 0 || error == WSAEWOULDBLOCK )
{
fd_set fd_write = {1, s};
timeval twait = {0, iTimeout * 1000};
error = select(0, NULL, &fd_write, NULL, &twait);
error = WSAGetLastError();
bIsAlive = FD_ISSET(s, &fd_write);
}
else
{
bIsAlive = (error == WSAECONNREFUSED);
}
shutdown(s, 2 /*SD_BOTH*/);
closesocket(s);
static int n = 0;
printf(_T("%04d: isHostAlive(%s) = %d sec, alive = %d\r\n"),
++n, pszHost, time(NULL) - start, bIsAlive);
return bIsAlive;
}
long cThreads = 0;
static void thread(void* p)
{
for( int i = 1; i < 1000; i++ )
{
isHostAlive(_T("<hostnamehere>"));
}
InterlockedDecrement(&cThreads);
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit:GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
return 1;
}
AfxSocketInit();
for( int i = 0; i < 10; i++ )
{
_beginthread(thread, 0, NULL);
InterlockedIncrement(&cThreads);
}
while( cThreads > 0 )
Sleep(100);
return nRetCode;
}