现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

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

2014-07-29 06:54 工业·编程 ⁄ 共 4123字 ⁄ 字号 暂无评论

#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;

  }

}

}

给我留言

留言无头像?