.
Environment: VC6, NT4/Win2K—should work on any 32-bit Windows operating system that has Winsock2 libraries.
Overview
Sample code for a network “ping” is relatively easy to find. CodeGuru has several good examples and the SDK sample code has another good example. So what about trace route? With a little research I discovered that doing a trace route is really no more difficult than a ping. With a few minor modifications to the ping sample, it is possible to do a multi-threaded trace route. Trace route is really just a ping with the “time-to-live” option set to any number from 1 to the number of hops it takes to get to the destination. So, if it takes 10 hops to get to the destination and the “time-to-live” option is set to 5, the IP address that gets returned is the address of the fifth router along the way. The logical question is: “How many hops does it take?” Well, you don’t really know until you get there. Basically, you just increment the time-to-live option until the returned IP address matches the destination IP address. The router names can be obtained by a simple call to “gethostbyaddr”.
To call this code “multi-threaded” is a bit of a misnomer. The execution of the pings and ultimately the trace route happens in a single thread; the user interface is in a separate thread. All that is accomplished by this approach is that the user may stop the processing and view updates asynchronously.
This code also relies heavily on the Winsock-2 library (ws2_32.lib).
An Outline of the Approach
- This process depends on three variables: destination address, returned address (coming back from ping), and ttl (time-to-live).
- Get the destination address by calling “gethostbyname”. Set the returned address to 0 and ttl to 1.
- While the returned address is not equal to the destination address, do the following: call ping, increment the ttl, and get the name of the returned address.
The Sample Code, Implementing the Approach
int TRThread::RunThread(void) { int result = 0; ClearAllItems(); InitSockLibrary(); struct hostent *hHost; struct sockaddr_in sin; // get the IP address of the destination HOSTENT * ent = gethostbyname(m_address); if (CheckKillFlag()) { return result; } if (ent && ent->h_addrtype == AF_INET) { in_addr * final_ptr = (struct in_addr*)ent->h_addr_list[0]; unsigned long ipfinal = final_ptr->S_un.S_addr; // initialize returned IP address and time-to-live (ttl) int ttl = 1; unsigned long ipback = 0; unsigned long ms = 0; while (ipback != ipfinal){ hHost = 0; TRDeviceItem * item = new TRDeviceItem; // By checking the "kill flag" often, we are trying to // provide a responsive and well behaved worker thread. if (CheckKillFlag()) { break; } // send a ping to the destination address, knowing that it // will only make it thru (ttl) routers before getting sent // back. if (Ping(m_address,ttl,ipback,ms)) { sin.sin_family = AF_INET; sin.sin_addr.S_un.S_addr = ipback; // get the name of the router that bounced the ping back // (ipback) hHost = gethostbyaddr((char*)&sin.sin_addr, 4, PF_INET); // set up an item for the linked list item->SetIPAddress((unsigned long)ipback); item->SetResponseTime(ms); // if the router information is not null, extract the // router name if (hHost) { item->SetName(hHost->h_name); } } ttl++; if (CheckKillFlag()) { break; } // synchronize block, locking access to linked list before // changing anything Wait(); { // add the item to the linked list if (m_first_item == 0) { m_first_item = m_current_item = item; } else { m_current_item->SetNextItem(item); m_current_item = item; } m_total_items++; result++; } Release(); // The base class (WorkerThread) stores a synchronized // variable usually used to calculate the percentage of // work done. This time we are using that variable to // store the number of hops so far. SetTotal(m_total_items); // If we're over the maximum number // of hops, let's break outta here. if (ttl > MAX_HOPS) { break; } } } return result; }
Some Information about the Sample Project
The sample project is basically an SDI application with a ListView. The trace route executes in a thread class derived from WorkerThread and the view class uses a timer to check the thread for updates. To execute the program, simply type in a Web site or Internet address and click Trace.
Downloads
Download demo project – 31 Kb