close raw socket timeout

January 23, 2013 at 23:56:58
Specs: Windows server 2008
Hi
I use raw socket to implement a ping program. I found a strange issue when close raw socket.
In Windows server 2008 it needs wait 2 seconds every time close socket. Same code works quite fast in Win7 and Windows Server 2003.
Is there any one meet similar issue??Needs your kind help.

The key functions of my ping program is following

int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
ECHOREQUEST echoReq;
static int nSeq = 1;
int nRet;

// Fill in echo request
echoReq.icmpHdr.Type = ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = (USHORT)GetCurrentThreadId();
echoReq.icmpHdr.Seq = nSeq++;

// Fill in some data to send
for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet;

// Save tick count when sent
echoReq.dwTime = GetTickCount();

// Put data in packet and compute checksum
echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));

// Send the echo request
nRet = sendto(s, /* socket */
(LPSTR)&echoReq, /* buffer */
sizeof(ECHOREQUEST),
0, /* flags */
(LPSOCKADDR)lpstToAddr, /* destination */
sizeof(SOCKADDR_IN)); /* address length */

return nRet;
}
int RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom,ECHOREPLY *echoReply)
{
int nRet;
int nAddrLen = sizeof(struct sockaddr_in);

// Receive the echo reply
nRet = recvfrom(s, // socket
(LPSTR)echoReply, // buffer
sizeof(ECHOREPLY), // size of buffer
0, // flags
(LPSOCKADDR)lpsaFrom, // From address
&nAddrLen); // pointer to address len
return nRet;
}
int WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds;

readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 0;
Timeout.tv_usec = g_nPingTimeout * 1000;
int nRet = select(1, &readfds, NULL, NULL, &Timeout);
return nRet;
}

INT Ping(UINT nRetries,string strHost)
{
SOCKET rawSocket;
LPHOSTENT lpHost;
UINT nLoop;
int nRet;
struct sockaddr_in saDest;
struct sockaddr_in saSrc;
DWORD dwTimeSent;
DWORD dwElapsed;
u_char cTTL;
char szDestIP[16];
std::string str;
char temp[TEMP_BUF_LEN];

DWORD dwThread = GetCurrentThreadId();
memset(temp,0,255);
ltoa(dwThread, temp, 10);
string strThread = temp;

// Lookup host
lpHost = gethostbyname(strHost.c_str());
if (lpHost == NULL)
{
str = "Host not found:" + strHost;
cout<<strThread<<":"<<str<<endl;
if (g_bEnableLog) g_log->LogString(2, strThread);
return PING_SOCK_ERROR;
}

// Setup destination socket address
saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
saDest.sin_family = AF_INET;
saDest.sin_port = 0;

memset(temp, 0, TEMP_BUF_LEN);
itoa(REQ_DATASIZE, temp,10);
string strSize = temp;
string strTarget = inet_ntoa(saDest.sin_addr);
//str = "Pinging " + strTarget + " with " + strSize + " bytes of data";
//cout<<str<<endl;

// Create a Raw socket
rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawSocket == SOCKET_ERROR)
{
WSAError("socket()");
return PING_SOCK_ERROR;
}

ltoa(rawSocket, temp,10);
string strSocket = temp;
str = "Create socket for target " + strTarget + " succeeded - " + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;

BOOL bPingPass = FALSE;

// Ping multiple times
for (nLoop = 0; nLoop < nRetries; nLoop++)
{
// Send ICMP echo request
nRet = SendEchoRequest(rawSocket, &saDest);
if (nRet == SOCKET_ERROR)
{
WSAError("sendto() " + strTarget);
break;
}

nRet = WaitForEchoReply(rawSocket);
if (nRet == SOCKET_ERROR)
{
WSAError("select() " + strTarget);
break;
}
if (!nRet)
{
str = "Pinging " + strTarget + " Request Timed Out, socket " + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;
}
else
{
ECHOREPLY reply;
nRet = RecvEchoReply(rawSocket, &saSrc, &reply);
if (nRet == SOCKET_ERROR)
{
WSAError("recvfrom() " + strTarget);
break;
}
memcpy(szDestIP, inet_ntoa(reply.ipHdr.iaSrc), 16);
if(reply.ipHdr.Protocol == IPPROTO_ICMP && !strcmp(szDestIP, strHost.c_str()))
{
if (reply.echoRequest.icmpHdr.Type == 0)
{
// Calculate elapsed time
dwTimeSent = reply.echoRequest.dwTime;
cTTL = reply.ipHdr.TTL;
dwElapsed = GetTickCount() - dwTimeSent;

if (dwElapsed <= g_nPingTimeout)
{
string strTarget = inet_ntoa(saDest.sin_addr);
memset(temp, 0, TEMP_BUF_LEN);
ltoa(dwElapsed, temp,10);
string strTime = temp;

memset(temp, 0, TEMP_BUF_LEN);
ltoa(cTTL, temp,10);
string strTTL = temp;
str = "Reply from " + strTarget + " with " + strSize + " bytes of data time=" + strTime + " TTL=" + strTTL + " socket=" + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;
bPingPass = TRUE;
break;
}
else
{
str = "Pinging " + strTarget + " time exceed 1000 ms, consider it as offline, " + " socket=" + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;
}
}
else
{
str = "Pinging " + strTarget + " failed" + " socket=" + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;
}
}
else
{
string strProtocol = (reply.ipHdr.Protocol == IPPROTO_ICMP)?"ICPM":"Others";
str = "Pinging target " + strTarget + " failed - Response from " + szDestIP + " with protocol " + strProtocol + ",socket=" + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;
}
}
}

str = "Close socket for target " + strTarget + " begin - " + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;

//shutdown( rawSocket, SD_BOTH );

nRet = closesocket(rawSocket);
if (nRet == SOCKET_ERROR)
WSAError("closesocket()");

str = "Close socket for target " + strTarget + " succeeded - " + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;

return (bPingPass)?PING_PASS:PING_FAILED;
}


See More: close raw socket timeout

Report •


#1
January 24, 2013 at 00:04:23

/////////////////////////
str = "Close socket for target " + strTarget + " begin - " + strSocket;
if (g_bEnableLog) g_log->LogString(2, str);
cout<<strThread<<":"<<str<<endl;

//shutdown( rawSocket, SD_BOTH );

nRet = closesocket(rawSocket);
if (nRet == SOCKET_ERROR)
WSAError("closesocket()");

str = "Close socket for target " + strTarget + " succeeded - " + strSocket;
///////////////////////////////

By the console output, i found it needs wait 2 seconds every time call closesocket(
rawSocket).

Very strange!!


Report •
Related Solutions


Ask Question