Creating a Multi-Threaded Trace Route
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
About the Author
More for Developers
Top Authors
- Voted: 13 times.
- Voted: 11 times.
- Voted: 11 times.
- Voted: 8 times.
- Voted: 8 times.
- Paul Kimmel 214 articles
- Zafir Anjum 120 articles
- 15Seconds.com 99 articles
- Tom Archer - MSFT 83 articles
- Jeffrey Juday 82 articles


All