用VC编写实现ping 功能的动态连接库

 #include <afxsock.h>
#define ICMP_ECHOREPLY 0
#define ICMP_ECHOREQ 8
// IP Header -- RFC 791
typedef struct tagIPHDR
{
 u_char  VIHL;   // Version and IHL
 u_char TOS;   // Type Of Service
 short TotLen;   // Total Length
 short ID;    // Identification
 short FlagOff;  // Flags and Fragment Offset
 u_char TTL;   // Time To Live
 u_char Protocol;  // Protocol
 u_short Checksum;  // Checksum
 struct in_addr iaSrc; // Internet Address - Source
 struct in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR;


// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
 u_char Type;   // Type
 u_char Code;   // Code
 u_short Checksum;  // Checksum
 u_short ID;    // Identification
 u_short Seq;   // Sequence
 char Data;   // Data
}ICMPHDR, *PICMPHDR;


#define REQ_DATASIZE 32  // Echo Request Data size

// ICMP Echo Request
typedef struct tagECHOREQUEST
{
 ICMPHDR icmpHdr;
 DWORD dwTime;
 char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;


// ICMP Echo Reply
typedef struct tagECHOREPLY
{
 IPHDR ipHdr;
 ECHOREQUEST echoRequest;
 char    cFiller[256];
}ECHOREPLY, *PECHOREPLY;

u_short in_cksum(u_short *addr, int len)
{
  int nleft = len;
  u_short *w = addr;
  u_short answer;
  int sum = 0;
  while( nleft > 1 )  {
  sum += *w++;
  nleft -= 2;
 }

 if( nleft == 1 ) {
  u_short u = 0;

  *(u_char *)(&u) = *(u_char *)w ;
  sum += u;
 }

 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
 sum += (sum >> 16);   /* add carry */
 answer = ~sum;    /* truncate to 16 bits */
 return (answer);
}

 

 


int WaitForEchoReply(SOCKET s)
{
 struct timeval Timeout;
 fd_set readfds;
 readfds.fd_count = 1;
 readfds.fd_array[0] = s;
 Timeout.tv_sec = 1;
    Timeout.tv_usec = 0;

 return(select(1, &readfds, NULL, NULL, &Timeout));
}


unsigned int RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
 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

 // Check return value

 // return time sent and IP TTL
 *pTTL = echoReply.ipHdr.TTL;

 return(echoReply.echoRequest.dwTime);     
}

 

 

 

 

 

extern "C" _declspec (dllexport)BOOL Ping(CString pstrHost, UINT nNumIp)
{
 ECHOREQUEST echoReq;
 int nId = 1;
 int nSeq = 1;
 SOCKET rawSocket;
 LPHOSTENT lpHost;
 UINT nLoop;
 int nRet;
 struct sockaddr_in saDest;
 struct sockaddr_in saSrc;
 DWORD dwTimeSent;
 DWORD dwElapsed;
 u_char cTTL;
 char *destIP = NULL;
 WSADATA wsaData;
 //创建一个Raw套节字
 if(WSAStartup(MAKEWORD(2,1), &wsaData))
 {
  return false;
 }
 rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
 if (rawSocket == SOCKET_ERROR)
 {
  nRet = closesocket(rawSocket);
  ::WSACleanup();
  return FALSE;
 }
 //获得主机信息
 lpHost = gethostbyname(pstrHost);
 if (lpHost == NULL)
 {
  nRet = closesocket(rawSocket);
  ::WSACleanup();
  return FALSE;
 }
 //构造目标套节字地址信息
 memset(&saDest, 0, sizeof(sockaddr_in));
 saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
 saDest.sin_family = AF_INET;
 saDest.sin_port = 0;
 //发送ICMP回应请求
 
// SendEchoRequest(rawSocket,&saDest);
 

 
 int rnRet;

 echoReq.icmpHdr.Type  = ICMP_ECHOREQ;
 echoReq.icmpHdr.Code  = 0;
 echoReq.icmpHdr.Checksum = 0;
 echoReq.icmpHdr.ID   = nId++;
 echoReq.icmpHdr.Seq   = nSeq++;

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

 // 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           
 rnRet = sendto(rawSocket,      /* socket */
     (LPSTR)&echoReq,   /* buffer */
     sizeof(ECHOREQUEST),
     0,       /* flags */
     (LPSOCKADDR)&saDest, /* destination */
     sizeof(SOCKADDR_IN));   /* address length */
 if (rnRet == SOCKET_ERROR)
 {
  rnRet = closesocket(rawSocket);
  ::WSACleanup();
  return FALSE;
 }

 nRet = WaitForEchoReply(rawSocket);
 if (nRet == SOCKET_ERROR){
  nRet = closesocket(rawSocket);
  ::WSACleanup();
  return FALSE;
 }
 if(!nRet){
  nRet = closesocket(rawSocket);
  ::WSACleanup();
  return FALSE;
 }
 else{
  //获得回应
  dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);
  //计算时间
  dwElapsed = GetTickCount() - dwTimeSent;
  ::Sleep(1000);
  destIP = inet_ntoa(saSrc.sin_addr);//获得客户IP地址
  if(pstrHost == destIP){
   nRet = closesocket(rawSocket);
   nRet = ::WSACleanup();
   return TRUE;
  }
  else
  {
   for(nLoop = 0; nLoop < nNumIp; nLoop++)
   {
    dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);
    destIP = inet_ntoa(saSrc.sin_addr);
    if(pstrHost == destIP)
    {
     nRet = closesocket(rawSocket);
     nRet = ::WSACleanup();
     return TRUE;
    }
   }
   nRet = closesocket(rawSocket);
   nRet = ::WSACleanup();
   return FALSE;
  }
 }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值