www.gusucode.com > 一些VC++网络编程实例源代码-源码程序 > 一些VC++网络编程实例源代码-源码程序\code\第十章\TraceRoute\TraceRoute1.cpp
//Download by http://www.NewXing.com // TraceRoute1.cpp: implementation of the CTraceRoute class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TraceRoute1.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CTraceRoute::CTraceRoute() { m_nTTL = 1; m_nMaxhops = MAX_HOPS; m_sockRaw = INVALID_SOCKET; m_RcvBuffer = NULL; m_IcmpData = NULL; m_nTimeout = 1000; m_bDone = FALSE; WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0) { printf("WSAStartup() failed: %d/n", WSAGetLastError()); } } CTraceRoute::~CTraceRoute() { } void CTraceRoute::ConnectToHost(char* strHost) { m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED); if (m_sockRaw == INVALID_SOCKET) { printf("WSASocket() failed: %d\n", WSAGetLastError()); ExitProcess(-1); } int ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_RCVTIMEO, (char *)&m_nTimeout, sizeof(m_nTimeout)); if (ret == SOCKET_ERROR) { printf("setsockopt(SO_RCVTIMEO) failed: %d\n", WSAGetLastError()); return ; } ret = setsockopt(m_sockRaw, SOL_SOCKET, SO_SNDTIMEO, (char *)&m_nTimeout, sizeof(m_nTimeout)); if (ret == SOCKET_ERROR) { printf("setsockopt(SO_SNDTIMEO) failed: %d\n", WSAGetLastError()); return ; } m_addrDest.sin_family = AF_INET; if ((m_addrDest.sin_addr.s_addr = inet_addr(strHost)) == INADDR_NONE) { HOSTENT* hp; hp = gethostbyname(strHost); if (hp) memcpy(&(m_addrDest.sin_addr), hp->h_addr, hp->h_length); else { printf("gethostbyname failed: %d\n", WSAGetLastError()); return ; } } int bOpt = TRUE; if (setsockopt(m_sockRaw, SOL_SOCKET, SO_DONTROUTE, (char *)&bOpt, sizeof(BOOL)) == SOCKET_ERROR) { printf("setsockopt failed: %d\n", WSAGetLastError()); return ; } m_nDatasize = DEF_PACKET_SIZE; m_nDatasize += sizeof(IcmpHeader); // // Allocate the sending and receiving buffers for ICMP packets // m_IcmpData = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET); m_RcvBuffer = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET); if ((!m_IcmpData) || (!m_RcvBuffer)) { printf("HeapAlloc() failed: %d\n", WSAGetLastError()); return ; } // Set the socket to bypass the standard routing mechanisms // i.e. use the local protocol stack to the appropriate network // interface // // // Here we are creating and filling in an ICMP header that is the // core of trace route. // memset(m_IcmpData, 0, MAX_PACKET); printf("\nTracing route to %s over a maximum of %d hops:\n\n", strHost, m_nMaxhops); fill_icmp_data(m_IcmpData, m_nDatasize); for(m_nTTL = 1; ((m_nTTL < m_nMaxhops) && (!m_bDone)); m_nTTL++) { int bwrote; // Set the time to live option on the socket // set_ttl(m_sockRaw, m_nTTL); // // Fill in some more data in the ICMP header // ((IcmpHeader*)m_IcmpData)->i_cksum = 0; ((IcmpHeader*)m_IcmpData)->timestamp = GetTickCount(); ((IcmpHeader*)m_IcmpData)->i_seq = m_nSeqno++; ((IcmpHeader*)m_IcmpData)->i_cksum = checksum((USHORT*)m_IcmpData, m_nDatasize); // // Send the ICMP packet to the destination // bwrote = sendto(m_sockRaw, m_IcmpData, m_nDatasize, 0, (SOCKADDR *)&m_addrDest, sizeof(m_addrDest)); if (bwrote == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { printf("%2d Send request timed out.\n", m_nTTL); continue; } printf("sendto() failed: %d\n", WSAGetLastError()); return ; } // Read a packet back from the destination or a router along // the way. // int fromlen; fromlen = sizeof(SOCKADDR); ret = recvfrom(m_sockRaw, m_RcvBuffer, MAX_PACKET, 0, (struct sockaddr*)&m_addrFrom, &fromlen); if (ret == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { printf("%2d Receive Request timed out.\n", m_nTTL); continue; } printf("recvfrom() failed: %d\n", WSAGetLastError()); return ; } // // Decode the response to see if the ICMP response is from a // router along the way or whether it has reached the destination. // m_bDone = decode_resp(m_RcvBuffer, ret, &m_addrFrom, m_nTTL); Sleep(1000); } } void CTraceRoute::fill_icmp_data(char * icmp_data, int datasize) { IcmpHeader *icmp_hdr; char *datapart; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr->i_type = ICMP_ECHO; icmp_hdr->i_code = 0; icmp_hdr->i_id = (USHORT)GetCurrentProcessId(); icmp_hdr->i_cksum = 0; icmp_hdr->i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); // // Place some junk in the buffer. Don't care about the data... // memset(datapart,'E', datasize - sizeof(IcmpHeader)); } int CTraceRoute::set_ttl(SOCKET s, int nTimeToLive) { int nRet; nRet = setsockopt(s, IPPROTO_IP, IP_TTL, (LPSTR)&nTimeToLive, sizeof(int)); if (nRet == SOCKET_ERROR) { printf("setsockopt(IP_TTL) failed: %d\n", WSAGetLastError()); return 0; } return 1; } USHORT CTraceRoute::checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if(size ) cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (USHORT)(~cksum); } void CTraceRoute::Cleanup() { HeapFree(GetProcessHeap(), 0, m_RcvBuffer); HeapFree(GetProcessHeap(), 0, m_IcmpData); if (m_sockRaw != NULL) closesocket(m_sockRaw); WSACleanup(); } int CTraceRoute::decode_resp(char *buf, int bytes, SOCKADDR_IN *from, int ttl) { IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; struct hostent *lpHostent = NULL; struct in_addr inaddr = from->sin_addr; iphdr = (IpHeader *)buf; // Number of 32-bit words * 4 = bytes iphdrlen = iphdr->h_len * 4; if (bytes < iphdrlen + ICMP_MIN) printf("Too few bytes from %s\n", inet_ntoa(from->sin_addr)); icmphdr = (IcmpHeader*)(buf + iphdrlen); switch (icmphdr->i_type) { case ICMP_ECHOREPLY: // Response from destination lpHostent = gethostbyaddr((const char *)&from->sin_addr, AF_INET, sizeof(struct in_addr)); if (lpHostent != NULL) printf("%2d %s (%s)\n", ttl, lpHostent->h_name, inet_ntoa(inaddr)); return 1; break; case ICMP_TIMEOUT: // Response from router along the way printf("%2d %s\n", ttl, inet_ntoa(inaddr)); return 0; break; case ICMP_DESTUNREACH: // Can't reach the destination at all printf("%2d %s reports: Host is unreachable\n", ttl, inet_ntoa(inaddr)); return 1; break; default: printf("non-echo type %d recvd\n", icmphdr->i_type); return 1; break; } return 0; }