以前我們描述了I P記錄路由選項(xiàng)(R R)。為什么不使用這個(gè)選項(xiàng)而另外開發(fā)一個(gè)新的應(yīng)用程序?有三個(gè)方面的原因。首先,原先并不是所有的路由器都支持記錄路由選項(xiàng),因此該選項(xiàng)在某些路徑上不能使用(Tr a c e r o u t e 程序不需要中間路由器具備任何非凡的或可選的功能)。 其次,記錄路由一般是單向的選項(xiàng)。發(fā)送端設(shè)置了該選項(xiàng),那么接收端不得不從收到的I P 首部中提取出所有的信息,然后全部返回給發(fā)送端。在7 . 3節(jié)中,我們看到大多數(shù)P i n g服務(wù)器的實(shí)現(xiàn)(內(nèi)核中的I C M P回顯應(yīng)答功能)把接收到的R R清單返回,但是這樣使得記錄下來的I P地址翻了一番(一來一回)。這樣做會(huì)受到一些限制,這一點(diǎn)我們?cè)谙乱欢斡懻摚═r a c e r o u t e 程序只需要目的端運(yùn)行一個(gè)U D P模塊—其他不需要任何非凡的服務(wù)器應(yīng)用程序)。 最后一個(gè)原因也是最主要的原因是,I P首部中留給選項(xiàng)的空間有限,不能存放當(dāng)前大多數(shù)的路徑。在I P首部選項(xiàng)字段中最多只能存放9個(gè)I P地址。在原先的A R PA N E T中這是足夠的,但是對(duì)現(xiàn)在來說是遠(yuǎn)遠(yuǎn)不夠的。 Tr a c e r o u t e 程序使用I C M P報(bào)文和I P首部中的T T L字段(生存周期)。T T L字段是由發(fā)送端初始設(shè)置一個(gè)8 bit 字段。推薦的初始值由分配數(shù)字R F C指定,當(dāng)前值為6 4。較老版本的系統(tǒng)經(jīng)常初始化為1 5或3 2。我們從第7章中的一些p i n g程序例子中可以看出,發(fā)送I C M P回顯應(yīng)答時(shí)經(jīng)常把T T L設(shè)為最大值2 5 5。 每個(gè)處理數(shù)據(jù)報(bào)的路由器都需要把T T L的值減1或減去數(shù)據(jù)報(bào)在路由器中停留的秒數(shù)。由于大多數(shù)的路由器轉(zhuǎn)發(fā)數(shù)據(jù)報(bào)的時(shí)延都小于1秒鐘,因此T T L最終成為一個(gè)跳站的計(jì)數(shù)器,所經(jīng)過的每個(gè)路由器都將其值減1。 RFC1009 [Braden and Postel 1987]指出,假如路由器轉(zhuǎn)發(fā)數(shù)據(jù)報(bào)的時(shí)延超過1秒,那么它將把T T L值減去所消耗的時(shí)間(秒數(shù))。但很少有路由器這么實(shí)現(xiàn)。新的路由器需求文檔RFC[Almquist 1993]為此指定它為可選擇功能,答應(yīng)把T T L看成一個(gè)跳站計(jì)數(shù)器。 T T L字段的目的是防止數(shù)據(jù)報(bào)在選路時(shí)無休止地在網(wǎng)絡(luò)中流動(dòng)。例如,當(dāng)路由器癱瘓或者兩臺(tái)路由器之間的連接丟失時(shí),選路協(xié)議有時(shí)會(huì)去檢測(cè)丟失的路由并一直進(jìn)行下去。在這段時(shí)間內(nèi),數(shù)據(jù)報(bào)可能在循環(huán)回路被終止。T T L字段就是在這些循環(huán)傳遞的數(shù)據(jù)報(bào)上加上一個(gè)生存上限。 當(dāng)路由器收到一份I P數(shù)據(jù)報(bào),假如其T T L字段是0或1,則路由器不轉(zhuǎn)發(fā)該數(shù)據(jù)報(bào)(接收到這種數(shù)據(jù)報(bào)的目的主機(jī)可以將它交給應(yīng)用程序,這是因?yàn)椴恍枰D(zhuǎn)發(fā)該數(shù)據(jù)報(bào)。但是在通常情況下,系統(tǒng)不應(yīng)該接收T T L字段為0的數(shù)據(jù)報(bào))。相反,路由器將該數(shù)據(jù)報(bào)丟棄,并給信源機(jī)發(fā)一份I C M P“超時(shí)”信息。Tr a c e r o u t e 程序的要害在于包含這份I C M P信息的I P報(bào)文的信源地址是該路由器的I P地址。 我們現(xiàn)在可以猜想一下Tr a c e r o u t e 程序的操作過程。它發(fā)送一份T T L字段為1的I P數(shù)據(jù)報(bào)給目的主機(jī)。處理這份數(shù)據(jù)報(bào)的第一個(gè)路由器將T T L值減1,丟棄該數(shù)據(jù)報(bào),并發(fā)回一份超時(shí)I C M P報(bào)文。這樣就得到了該路徑中的第一個(gè)路由器的地址。然后Tr a c e r o u t e 程序發(fā)送一份T T L值為2的數(shù)據(jù)報(bào),這樣我們就可以得到第二個(gè)路由器的地址。繼續(xù)這個(gè)過程直至該數(shù)據(jù)報(bào)到達(dá)目的主機(jī)。但是目的主機(jī)哪怕接收到T T L值為1的I P數(shù)據(jù)報(bào),也不會(huì)丟棄該數(shù)據(jù)報(bào)并產(chǎn)生一份超時(shí)I C M P報(bào)文,這是因?yàn)閿?shù)據(jù)報(bào)已經(jīng)到達(dá)其最終目的地。那么我們?cè)撊绾闻卸ㄊ欠褚呀?jīng)到達(dá)目的主機(jī)了呢? Tr a c e r o u t e 程序發(fā)送一份U D P數(shù)據(jù)報(bào)給目的主機(jī),但它選擇一個(gè)不可能的值作為U D P端口號(hào)(大于30 000),使目的主機(jī)的任何一個(gè)應(yīng)用程序都不可能使用該端口。因?yàn)椋?dāng)該數(shù)據(jù)報(bào)到達(dá)時(shí),將使目的主機(jī)的U D P模塊產(chǎn)生一份“端口不可達(dá)”錯(cuò)誤(見6 . 5節(jié))的I C M P報(bào)文。這樣,Tr a c e r o u t e 程序所要做的就是區(qū)分接收到的I C M P報(bào)文是超時(shí)還是端口不可達(dá),以判定什么時(shí)候結(jié)束。 Tr a c e r o u t e 程序必須可以為發(fā)送的數(shù)據(jù)報(bào)設(shè)置T T L字段。并非所有與T C P / I P接口的程序都支持這項(xiàng)功能,同時(shí)并非所有的實(shí)現(xiàn)都支持這項(xiàng)能力,但目前大部分系統(tǒng)都支持這項(xiàng)功能,并可以運(yùn)行Tr a c e r o u t e 程序。這個(gè)程序界面通常要求用戶具有超級(jí)用戶權(quán)限,這意味著它可能需要非凡的權(quán)限以在你的主機(jī)上運(yùn)行該程序。