手冊tcpip詳解卷2實現_第1頁
手冊tcpip詳解卷2實現_第2頁
手冊tcpip詳解卷2實現_第3頁
手冊tcpip詳解卷2實現_第4頁
手冊tcpip詳解卷2實現_第5頁
已閱讀5頁,還剩28頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第22章協議控制塊22.1引言協議層使用協議控制塊(PCB)存放各UDP和TCP插口所要求的多個信息片。ernet協議維護ernet 協議控制塊(ernet protocol control block)和TCP控制塊(TCP control block)。因為UDP是無連接的,所以一個控制塊。點需要的所有信息都可以在ernet PCB中找到;不存在UDPernet PCB含有所有UDP和TCP點共有的信息:外部和本地 IP地址、外部和本地端號、IP首部原型、該點使用的IP選項以及一個指向該點目的地址選路表的指針。TCP控制塊包含了TCP為各連接的所有結點信息:兩個方向的序號、窗口大小、重傳次

2、數等等。本章描述Net/3所用的ernet PCB,在詳細TCP時再探討TCP控制塊。研究幾個操作開頭。ernet PCB的函數,會在描述UDP和TCP時遇到它們。大多數的函數以 in_pcb圖22-1總結了協議控制塊以及它們與 file和socket結構之間的關系。該圖中有幾點要考慮:當socket或accept創建一個插口后,插口層生成一個file結構和一個socket結構。文件類型是DTYPE_SOCKET,UDP插口類型是SOCK_STREAM。點的插口類型是SOCK_DGRAM,TCP點的然后調用協議層。UDP創建一個結構上: so_pcb成員指向iernet PCB(一個ib結構)

3、,并把它到socketb結構,inp_socket成員指向socket結構。TCP做同樣的工作,也創建它自己的控制塊 (一個tcpcb結構),并用指針inp_ppcb和t_ib把它到ib上。在兩個UDP ib中,inp_ppcb成員是一個空指針,因為UDP不負責它自己的控制塊。顯示的其他四個ib結構的成員,從inp_faddr到inp_lport,形成了該點的插口對:外部IP地址和端,以及本地IP地址和端。UDP和TCP用指針inp_next和inp_prev一個所有ernet PCB的雙向鏈表。它們在表頭分配一個全局ib結構(命名為udb和tcb),在該結構中只使用三個成員:下一個和前一個指

4、針,以及本地端。后一個成員中包含了該協議使用的下一個臨時端ernet PCB是一個傳輸層數據結構。 TCP、UDP和原始IP使用它,但IP、ICMP或ICMP不用它。還沒有講過原始IP,但它也用ernet PCB。與TCP和UDP不同,原始IP在PCB中不成員,原始 I P只用本章中提到的兩個函數:i n _ p c b a l l o c 分配 P C B ,用端in_pcbdetachPCB。第32章將原始IP。第 22 章 協議控制塊計計573圖22-1ernet協議控制塊以及與其他結構之間的關系22.2代碼介紹所有PCB函數都在一個C文件和一個包含定義的頭文件中,如圖 22-2所示。圖

5、22-2 本章中的文件文件描述netinet/in_pcb.h netinet/in_pcb.cin_pcb結構定義PCB函數 描述符 描述符 描述符 描述符插口層協議層所有UDP的雙向循環鏈表ernet協議控制塊所有TCP的雙向循環鏈表ernet協議控制塊和相關的TCP控制塊574計計TCP/IP詳解 卷2:實現22.2.1 全局變量本章只引入一個全局變量,如圖 22-3所示。圖22-3 本章中引入的全局變量22.2.2 統計量ernet PCB和TCP PCB都是內核的malloc函數分配的M_PCB類型。這只是內核分配的大約60種不同類型內存的一種。例如, mbuf的類型是M_BUF,s

6、ocket結構分配的類型是 M_SOCKET。因為內核保持所分配的不同類型內存緩存的計數器,所以著幾個 PCB數量的統計量。-m命令顯示的是mbuf分配統計vms 信息。-m命令顯示內核的內存分配統計信息, nets 22.3ib的結構圖22-4是ib結構的定義。這不是一個大結構,只占 84個字節。圖22-4 i b 結構4 3 - 4 5inp_next和inp_prev為UDP和TCP的所有PCB形成一個雙向鏈表。另外,每個PCB都有一個指向協議鏈表表頭的指針 (inp_head)。對UDP表上的PCB,inp_head總是指向udb(圖22-1);對TCP表上的PCB,這個指針總是指向t

7、cb。4 6 - 4 9這個IP下面四個成員: inp_faddr、inp_fport、inp_laddr和inp_lport,包含了點的插口對:外部IP地址和端,以及本地IP地址和端。PCB中以網絡字節序而不是以主機字節序這四個值。層的TCP和UDP都使用ernet PCB。盡管在這個結構里保存本地和外部 IP地址很有意義,但端并不屬于這里。端及其大小的定義是由各層協議變量數 據 類 型描述zeroin_addrstruct in_addr 32 bit 全零IP地址第 22 章 協議控制塊計計575指定的,不同的層可以指定不同的值。 Partridge 1987 提出了這個問題,其中版本1

8、的RDP采用8 bit的端,需要用 8 bit的端重新實現幾個標準內核程序。版本2的RDP Partridge和Hinden 1990 采用16 bit端。實際上,端屬于層控制塊,例如TCP的tcpcb。可能會要求采用一種新的 UDP的PCB。盡管這個方案可行,但卻可能使馬上要的幾個程序復雜化。5 0 - 5 1inp_socket是一個指向該PCB的socket結構的指針, inp_ppcb是一個指針,它指向這個PCB的可選層控制塊。在圖 22-1中看到, inp_ppcb和TCP一起指應的tcpcb,但UDP不用它。socket和ib之間的是雙向的,因為有時內核從插口層開始,需要對應的er

9、net PCB( 如用戶輸出),而有時內核從 PCB開始,需要找到對應的socket結構(如處理收到的IP數據報)。5 2如果IP有一個到外部地址的路由,則它被保存在 ipp_route處。看到,當收到一個ICMP重定向報文時,將掃描所有ernet PCB,找到那些外部IP地址與重定向IP地址匹配的PCB,將其inp_route條到該外部地址的新路由。標記成無效。當再次將該 PCB用于輸出時,迫使IP重新找一5 3 inp_flags成員中存放了幾個標志。圖22-5顯示了各標志。A D D R圖22-5 inp_flags 值5 4PCB中一個IP首部的備份,但它只使用其中的兩個成員, TOS

10、和TTL。TOS被初始化為0(普通業務),TTL被層初始化。看到, TCP和UDP都把TTL的默認值設為 64。進程可以用IP_TOS或IP_TTL插口選項改變這些默認值,新的值在 ib-inp_ip結構中。以后, TCP和UDP在發送IP數據報時,卻把該結構用作原型IP首部。5 5 - 5 6進程也可以用IP_OPTIONS插口選項設置外出數據報的IP選項。函數ip_pcbopts把調用方選項的備份存放在一個 mbuf中,inp_options成員是一個指向該mbuf的指針。每次TCP和UDP調用ip_output函數時,就把一個指向這些IP首部的指針傳給IP,IP將其插到出去的IP數據報中

11、。類似地, inp_moptions成員是一個指向用戶IP多播選項備份的指針。22.4in_pcballoc和in_pcbdetach函數在創建插口時, TCP、UDP和原始IP會分配一個ernet PCB。系統調用socket發布PRU_ATTACH請求。在UDP情況下,struct socket *so; error;error = in_pcballoc(so, &udb);圖22-6是in_pcballoc函數。1. 分配PCB,初始化為零在圖23-33中看到,產生的調用是inp_flags描述I N P _ H D R I N C LI N P _ R E C V O P T SI

12、N P _ R E C V R E T O P T S I N P _ R E C V D S T A D D R進程提供整個IP首部(只有原始插口)把到達IP選項作為控制信息接收(只有UDP,還沒有實現) 把回答的IP選項作為控制信息接收(只有UDP,還沒有實現)把IP目的地址作為控制信息接收(只有UDP)I N P _ C O N T R O L O P T SI N P _ R E C V O P T S | I N P - R E C V R E T O P T S | I N P _ R E C V D S T576計計TCP/IP詳解 卷2:實現圖22-6 in_pcballoc函

13、數:分配一個ernet PCB3 6 - 4 5in_pcballoc使用宏MALLOC調用內核的內存分配器。因為這些PCB總是作為系統調用的結果分配的,所以總能等到一個。Net/2和早期的版本把ernet PCB和TCP PCB都保存在mbuf中。它們的大小分別是80和108字節。Net/3版本中的大小變成了 84和140字節,所以TCP控制塊不再適合存放在mbuf中。Net/3使用內核的內存分配器而不是mbuf分配兩種控制塊。細心的讀者會注意到圖 2-6的例子中,為PCB分配了17個mbuf,而剛剛講到Net/3不再用mbuf存放ernet PCB和TCP PCB。但是, Net/3的確用

14、mbuf存放Unix域的PCB,這就是計數器所指的。 nets輸出的mbuf統計信息是針對內核為所有協議族分配的mbuf,而不僅僅是ernet協議族。bzero把PCB設成0。這非常重要,因為PCB 中的IP地址和端必須被初始化成 0。圖22-7 in_pcbdetach 函數:一個ernet PCB2. 把結構起來4 6 - 4 9in_head成員指向協議的PCB表頭(udb或tcp),inp_socket成員指向socket結第 22 章 協議控制塊計計577構,新的PCB結構被加到協議的雙向鏈表上(insque),socket結構指向該PCB。insque函數把新的PCB放到協議表的表

15、頭里。在發布PRU_DETACH請求后,一個ernet PCB,這是在關閉插口時發生的。圖 22-7顯示了in_pcbdetach函數,最后將調用它。2 5 2 - 2 6 3socket結構中的PCB指針被設成0,sofree該結構。如果給這個PCB分配的是一個有IP選項的mbuf,則由m_free將其。如果該PCB 中有一個路由,則由rtfree將其。所有多播選項都由ip_freemoptions。2 6 4 - 2 6 5 remque把該PCB從協議的雙向鏈表中移走,該PCB使用的內存被返回給內核。22.5綁定、連接和分用在研究綁定插口、連接插口和分用進入的數據報的內核函數之前,對這些

16、動作施加的限制規則。1. 綁定本地IP地址和端先來看一下內核圖22-8是進程在調用bind時可以指定的本地IP地址和本地端的六種組合。前三行通常是服務器的 它們綁定某個特定端口,稱為服務器的知名端口 (well-known port),客戶都知道這些端口的值。后三行通常是客戶的 它們不考慮本地的端口,稱為臨時端口(ephemeral port),只要它在客戶主機上是唯一的。大多數服務器和客戶在調用 bind時,都指定通配IP地址。如圖22-8所示,在第3行和第6行中,用*表示。圖22-8 bind 的本地IP地址和本地端的組合如果服務器把某個特定IP地址綁定到某個插口上(也就是說,不是通配地址

17、),那么進入的 IP數據報中,只有那些以該特定IP地址作為目的IP地址的IP數據報 不管是單播、廣播或多播 都被交付給該進程。自然地,當進程把某個特定單播或廣播 IP地址綁定到某個插口上時,內核驗證該IP地址與一個本地接口對應。盡管可能,但很少出現客戶程序綁定某個特定 IP地址的情況(圖22-8中的第4行和第5行)。通常客戶綁定通配IP地址(圖22-8中的最后一行),讓內核根據自己選擇的到服務器的路由來選擇外出的接口。圖22-8沒有顯示如果客戶程序試圖綁定一個已經被其他插口使用的本地端口時會發生什么情況。默認情況下,如果一個端口已經被使用,進程是不能綁定它的。如果發生這種情況,則返回EADDR

18、INUSE差錯(地址正在被使用)。正在被使用(in use) 的定義很簡單,就是只要存在一個PCB,就把該端口作為它的本地端口。“正在被使用”的概念是相對于綁定協議的:TCP或UDP,因為TCP端與UDP端無關。本地IP地址本地端口描述單播或廣播多播*非零非零非零一個本地接口,特定端口 一個本地多播組,特定端口任何本地接口或多播組,特定端口單播或廣播多播*000一個本地接口,內核選擇端口一個多播組,內核選擇端口 任何本地接口,內核選擇端口578計計TCP/IP詳解 卷2:實現Net/3允許進程指定以下兩個插口選項來改變這個默認行為:允許進程綁定一個正在被使用的端 ,但被綁定的 IP地址(包括通

19、配地址)必須沒有被綁定到同一個端口。例如,如果連到的接口的IP地址是140.252.1.29,則一個插口可以被綁定到140.252.1.29,端口5555;另一個插口可綁定到 127.0.0.1,端口 5555;還有一個插口可以綁定到通配 IP地址,端口5555。在第二種和第三種情況下調用 b i n d 之前,必須先調用 s e t s o c k o p t ,設置SO_REUSEADDR選項。SO_REUSEADDRSO_REUSEPORT允許進程重用IP地址和端,但是包括第一個在內的各個 IP地址和端,必須指定這個插口選項。和 SO_REUSEADDR一樣,第一次綁定端時要指定插口選項

20、。例如,如果連到的接口具有 140.252.1.29的IP地址,并且某個插口綁定到140.252.1.29,端口6666,并指定SO_REUSEPORT插口選項,則另一個插口也可以指定同一個插口選項,并綁定140.252.1.29,端口6666。 在后一個例子中,當到達一個目的地址是 140.252.1.29,目的端口是本節的后面將6666的IP數據報時,會發生什么情況。因為這兩個插口都被綁定到該點上。SO_REUSEPORT是Net/3新加上的,在4.4BSD中是為支持多播而引入的。在這個版本之前,兩個插口是不可能綁定到同一個 IP地址和同一個端的。不幸的是, SO_REUSEPORT不是原

21、來的標準多播源程序的內容,所以對它的支持并不廣泛。其他支持多播的系統,如Solaris 2.x,讓進程指定SO_REUSEADDR來表明允許把多個端口綁定到同一IP地址和相同的端2. 連接一個UDP插口。通常把connect系統調用和TCP客戶聯系起來,但是UDP客戶或UDP服務器也可能調用connect,為插口指定外部IP地址和外部端交換UDP數據報。這就限制插口必須只與某個特定對方當連接UDP插口時,會有一個副作用:本地 IP地址,如果在調用bind時沒有指定,會自動被connect設置。它被設成由IP選路指定對方所選擇的本地接口地址。圖22-9顯示了UDP插口的三種不同的狀態,以及函數為

22、終止各狀態調用的偽代碼。圖22-9 UDP插口的本地和外部IP地址和端規范前三個狀態叫做已連接的UDP插口(connected UDP socket),后兩個叫做未連接的UDP插口(unconnected UDP socket)。兩個沒有連接上的UDP插口的區別在于,第一個具有一個完全本 地 插 口外 部 插 口描述localIP.lportforeignIP.fport限制到一個對方:socket(), bind(*.lport), connect(foreignIP, fport) socket(), bind(localIP, lport), connect(foreignIP, fpo

23、rt)localIP.lport*.*限制在本地接口上到達的數據報: localIPsocket(), bi n(dlocalIP, lport)*.lport*.*接收所有發到lport的數據報:socket(),bind(*, lport)第 22 章 協議控制塊計計579指定的本地地址,而第二個具有一個通配本地 IP地址。3. 分用TCP接收的IP數據報圖22-10顯示了主機sun上的三個net服務器的狀態。前兩個插口處于 LISTEN狀態,等待進入的連接請求,加三個連接到 IP地址是口處理在接口140.252.129上到達的連接請求,第二個本地IP地址是通配地址)。的主機上的端口 00

24、。第一個插插口將處理所有其他接口 (因為它的圖22-10 本地端口是23的三個TCP插口兩個具有未指定的外部 IP地址和端插口都顯示了出來,因為插口 API不允許的TCP服務器限制任何一個值。 TCP服務器必須accept客戶的連接,并在連接建立完成之后(也就是說,當TCP的三次握手結束之后)知客戶的IP地址和端。只有到這個時候,如果服務器不喜歡客戶的 IP地址和端是插口API通常的工作方式。,才能關閉連接。這并不是對 TCP要求的特性,這只當TCP收到一個目的端口是 23的報文段時,它調用 i n _ p c b l o o k u p,搜索它的整個ernet PCB表,找到一個匹配。馬上會

25、研究這個函數,將看到它有優先權,因為它的通配匹配(wildcard match)數最少。為了確定通配匹配數,只考慮本地和外部的 IP地址,不甚至不考慮 PCB。通配匹配數可以是 0、考慮外部端。本地端必須匹配,否則1(本地IP地址或外部IP地址)或2(本地和外部IP地址)。例如,假定到達報文段來自 140.252.1.11,端口1500,目的地是140.252.1.29,端口23。圖22-11是圖22-10中三個插口的通配匹配數。圖22-11 從140.252.1.11, 1500到140.252.1.29, 23的到達報文段第一個插口匹配這四個值,但有一個通配匹配 (外部IP地址)。第二個插

26、口也和到達報文段匹配,但有兩個通配匹配 (本地和外部IP地址)。第三個插口是一個沒有通配匹配的完全匹配。 Net/3使用第三個插口,它具有最小通配匹配數。繼續這個例子,假定到達報文段來自 140.252.1.11,端口1501,目的地是140.252.1.29,端口23。圖22-12顯示了通配匹配數。圖22-12 從140.252.1.11, 1501到140.252.1.29, 23的到達報文段本地地址本地端口外部地址外部端口TCP狀態通配匹配數140.252.1.29*140.252.1.29232323*140.252.1.11*1500LISTEN LISTEN ESTABLISHED

27、12本地地址本地端口外部地址外部端口TCP狀態通配匹配數140.252.1.29*140.252.1.29232323*140.252.1.11*1500LISTEN LISTEN ESTABLISHED120本地地址本地端口外部地址外部端口TCP狀態140.252.1.29*140.252.1.29232323*140.252.1.11*1500LISTEN LISTEN ESTABLISHED580計計TCP/IP詳解 卷2:實現第一個插口匹配有一個通配匹配;第二個插口匹配有兩個通配匹配;第三個插口根本不匹配,因為外部端 不相等 (只有當PCB中的外部IP地址不是通配地址時,才比較外部端口

28、號)。所以選擇第一個插口。在這兩個例子中, 沒有提到到達 TCP報文段的類型:假定圖 22-11中的報文段包含數據或對一個已經建立的連接的確認,因為它是發送到一個已經建立的插口上的。圖22-12中的報文段是一個到達的連接請求 (一個SYN),因為它是發送給一個正在還假定,的插口的。但是in_pcblookup的分用代碼并不關心這些。如果 TCP報文段對交付的插口來說是錯在后面看到, TCP會處理這種情況。現在,重要的是,分用代碼只把 IP數誤的類型,據報中的源和目的插口對的值與PCB中的值進行比較。4. 分用UDP接收的IP數據報UDP數據報的交付比剛才研究的 TCP的例子要復雜得多,因為可以

29、把 UDP數據報發送到一個廣播或多播地址。因為 Net/3(以及大多數支持多播的系統 )允許多個插口有相同的本地IP地址和端口,所以如何處理多個接收方的情況呢? Net/3的規則是:把目的地是廣播IP地址或多播IP地址的到達UDP數據報交付給所有匹配的插口。這里沒有“最好的”匹配的概念(也就是具有最小通配匹配數的匹配)。把目的地是單播IP地址的到達UDP數據報只交付給一個匹配的插口,就是具有最小通配匹配數的插口。如果有多個插口具有相同的“最小”通配匹配數,那么具體由哪個插口來接收到達數據報依賴于不同的實現。圖22-13顯示了四個在后面例子中使用的 UDP插口。要使四個UDP插口具有相同的本地端

30、IP地址和端需要使用SO_REUSEADDR或SO_REUSEPORT。前兩個插口已經被連接到一個外部,后面兩個沒有任何連接。圖22-13 四個本地端口為577的UDP插口考慮目的地是 1 4 0 . 2 5 2 . 1 3 . 6 3 ( 位于子網 1 4 0 . 2 5 2 . 1 3 上的廣播地址 ) ,端口 5 7 7 ,來自140.252.13.34,端口1500。圖22-14顯示它被交付給第三和第四個插口。圖22-14 接收從140.252.13.34, 1500到140.252.13.63, 577的數據報廣播數據報不交付給第一個插口,因為本地 IP地址和目的IP地址不匹配,外部

31、IP地址和源 IP地址也不匹配。也不把它交付給第二個插口,因為外部 IP地址和源IP地址不匹配。對于下一個例子,考慮目的地是140.252.129(一個單播地址),端口577,來自140 252 1.111,本地地址本地端口外部地址外部端付?140.252.1.29140.252.13.63140.252.13.63*577577577577140.252.1.11140.252.13.35*15001500*不,本地和外部IP不匹配不,外部IP不匹配交付交付本地地址本地端口外部地址外部端口說明140.252.1.29140.252.13.63140.252.13.63*57757757757

32、7140.252.1.11140.252.13.35*15001500*已連接,本地IP = 單播已連接,本地IP = 廣播未連接,本地IP = 廣播未連接,本地IP = 通配地址第 22 章 協議控制塊計計581端口1500。圖22-15顯示了把該數據報交付給哪個端口。圖22-15 接收從140.252.1.11, 1500到140.252.1.29, 577的數據報該數據報和第一個插口匹配,且沒有通配匹配;也和第四個插口匹配,但有兩個通配匹配。所以,它被交付給第一個插口,最好的匹配。22.6in_pcblookup函數in_pcblookup函數有幾個作用:1) 當TCP或UDP收到一個I

33、P數據報時, in_pcblookup掃描協議的ernet PCB表,尋找一個匹配的PCB,來接收該數據報。這是層對收到數據報的分用。2) 當進程執行bind系統調用,為某個插口分配一個本地 IP地址和本地端用in_pcbbind,驗證請求的本地地址對沒有被使用。時,協議調3) 當進程執行bind系統調用,請求給它的插口分配一個臨時端口時,內核選了一個臨時端口,并調用in_pcbbind檢查該端口是否正在被使用。如果正在被使用,就試下一個端口號,以此類推,直到找到一個沒有被使用的端。4) 當進程顯式或隱式地執行connect系統調用時, in_pcbbind驗證請求的插口對是唯一的(當在一個沒

34、有連接上的插口上發送一個 UDP數據報時,會隱式地調用connect,在第23章看到這種情況)。在第2種、第3種和第4種情況下, in_pcbbind調用in_pcblookup。兩個選項使該函數的邏輯顯得有些。首先,進程可以指定 SO_REUSEADDR或SO_REUSEPORT插口選項,表明允許本地地址。其次,有時通配匹配也是允許的 (例如,一個到達UDP數據報可以和一個自己的本地 IP地址有通配符的PCB匹配,意味著該插口將接收在任何本地接口上到達的 UDP數據報),而其他情況下,一個通配匹配是的(例如,當連接到一個外部IP地址和端時)。在原始的標準IP多播代碼中,出現了這樣的注釋“ i

35、n_pcblookup的邏輯比較模糊,也沒有一點說明” 。形容詞模糊比較保守。公開的IP多播碼是BSD386的,是由Craig Leres從4.4BSD派生而來的。他修改了該函數過載的語義,只對上面的第 1種情況使用in_pcblookup。第2種和第4種情況由一個新函數in_pcb處理。情況3由新函數in_uniqueport處理。把原來的功能分成幾個獨立的函數就顯得更清楚了,但在整個邏輯還是結合在一個函數in_pcblookup中。圖22-16顯示了in_pcblookuup函數。描述的 Net/3版本中,該函數從協議的PCB表的表頭開始,并可能會遍歷表中的每個 PCB。變量match了到

36、目前為止最佳匹配的指針, matchwild在該匹配中的通配匹配數。后者被初始化本地地址本地端口外部地址外部端付?140.252.1.29140.252.13.63140.252.13.63*577577577577140.252.1.11140.252.13.35*15001500*交付, 0個通配匹配不,本地和外部IP不匹配不,本地IP不匹配不,2個通配匹配582計計TCP/IP詳解 卷2:實現成3,比可能遇到的最大通配匹配數還大(任何大于2的值都可以)。每次循環時, wildcard從 0開始,計數每個PCB的通配匹配數。1. 比較本地端。如果PCB 的本地端口和lport參數不匹配,則

37、忽略該PCB。第一個比較的是本地端圖22-16in_pcblookuup 函數:搜索所有PCB尋找匹配第 22 章 協議控制塊計計5832. 比較本地地址4 1 94 2 7in_pcblookup比較PCB內的本地地址和laddr參數。如果有一個是通配地址,另一個不是,則wildcard計數器加1。如果都不是通配地址,則它們必須一樣;否則忽略這個PCB 。如果都是通配地址,則什么也不改變:它們不可比,也不增加 wildcard計數器。圖22-17對四種不同的情況做了小結。圖22-17 in_pcblookup 做的四種IP地址比較3. 比較外部地址和外部端4 2 84 3 7 這幾行完成與剛

38、才講的同樣的檢查,但是用外部地址而不是本地地址。而且,如果兩個外部地址都不是通配地址,則不僅兩個 IP地址必須相等,而且兩個外部端口也必須相等。圖22-18對外部IP地址的比較作了總結。圖22-18 in_pcblookup 做的四種外部IP地址比較可以對圖22-18中的第二行進行另外的外部端比較,因為一個 PCB不可能具有非通配外部地址,且外部端為 0。這個限制是由connect加上的,馬上就會看到,該函數要求一個非通配外部 IP地址和一個非零外部端口。但是,也可能,并且通常都是具有一個通配本地地址和一個非零本地端口。4. 檢查是否允許通配匹配在圖 22-10和圖22-13看到過這種情況。4

39、 3 84 3 9參數flags可以被設成INPLOOKUP_WILDCARD,意味著允許匹配中包含通配匹配。如果在匹配中有通配匹配(wildcard非零),并且調用方沒有指定這個標志位,則忽略這個PCB。當TCP和UDP調用這個函數分用一個到達數據報時,總是把 INPLOOKUP_WILDCARD置位,因為允許通配匹配(記住用圖22-10和圖22-13所作的例子)。但是,當這個函數作為connect系統調用的一部分而調用時,為了驗證一個插口對沒有被使用,把flags參數設成0。5.最佳匹配,如果找到確切匹配,則返回4 4 0 - 4 4 7這些語句到目前為止找到的最佳匹配。重復一下,最佳匹配

40、是具有最小通配匹配數的匹配。如果一個匹配有一個或兩個通配匹配,則該匹配,循環繼續。但是,如果找到一個確切的匹配(wildcard是0),則循環終止,返回一個指向該確切匹配 PCB的指針。例子 分用收到的TCP報文段圖22 - 19取自在圖 22 - 11中的TCP的例子。假定 i n _ p c b l o o k u p正在分用一個從140.252.1.11即端口1500到140.252.1.29即端口23的數據報。還假定PCB的順序是圖中行的順序。PCB外部IPfaddr參數描述不是*不是*不是*不是*wildcard+比較IP地址和端口,如果不相等,則略過PCB不能比較wildcard+

41、PCB本地IPladdr參數描述不是*不是*不是*不是*wildcard+比較IP地址,如果不相等,則略過PCB不能比較wildcard+584計計TCP/IP詳解 卷2:實現laddr是目的IP地址,lport是目的TCP端口,faddr是源IP地址,fport是源TCP端口。圖22-19 laddr =140.252.1.29,lport= 23,faddr = 140.252.1.11,fport= 1500當把第一行和到達報文段比較時, w i l d c a r d 是1 ( 外部I P 地址) , f l a g s 被設成 INPLOOKUP_WILDCARD,所以把match設

42、成指向該PCB,matchwild設為1。因為還沒有找到確切的匹配,所以循環繼續。下一次循環中, wildcard是2(本地和外部IP地址),因為比m a t c h w i l d 大,所以不該matchwild(1)小,所以把這個,循環繼續。再次循環時,w i l d c a r d是0 ,比在 match中。因為已經找到了一個確切的地址,所以終止循環,把指向該PCB的指針返回給調用方。如果TCP和UDP只用in_pcblookup來分用到達數據報,就可以對它進行簡化。首先,沒有必要檢查faddr或laddr是否是通配地址,因為它們是收到數據報的源和目的 IP地址。參數flags以及與相應

43、的檢測也可以不要,因為允許通配匹配。這一節了 i n _ p c b l o o k u p 函數的機制。在i n _ p c b b i n d 和in_pcbconnect如何調用這個函數后,將繼續回來22.7in_pcbbind函數下一個函數in_pcbbind,把一個本地地址和端調用它:它的意義。綁定到一個插口上。從五個函數中bind為某個TCP插口調用(通常綁定到服務器的一個知名端口上);bind為某個UDP插口調用(綁定到服務器的一個知名端口上,或者綁定到客戶插口的一個臨時端口上);connect為某個TCP插口調用,如果該插口還沒有綁定到一個非零端口上 (對TCP客戶來說,這是一

44、種典型情況);listen為某個TCP 插口調用,如果該插口還沒有綁定到一個非零端口 (這很少見,因為是TCP 服務器調用listen,TCP服務器通常綁定到一個知名端口上,而不是臨時端口 );5) 從in_pcbconnect(22.8節)調用,如果本地 IP地址和本地端被置位 (當為一個UDP插口調用connect,或為一個未連接UDP插口調用sendto時,這種情況比較典型)。在第3種、第4種和第5種情形下,把一個臨時端(在它已經被置位的情況下)。綁定到該插口上,不改變本地 IP地址稱情形1和情形2為顯式綁定(explicit bind),情形3、4和5為隱式綁定(implicit bi

45、nd)。也注意到,盡管在情形 2時,服務器綁定到一個知名端口是很正常的,但那些用過程調用(RPC)啟動的服務器也常常綁定到臨時端口上,然后用其他程序它們的臨時端口,該程序在該服務器的RPC程序號與其臨時端口之間的射器)。(例如,卷1的29.4節描述的Sun端口映PCB值wildcard本地地址本地端口外部地址外部端口140.252.1.29*140.252.1.29232323*140.252.1.11*1500120第 22 章 協議控制塊計計585分三部分顯示in_pcbbind函數。圖22-20是第一部分。圖22-20 in_pcbbind 函數:綁定本地地址和端6 4 - 6 7前兩個

46、測試驗證至少有一個接口已經被分配了一個 IP地址,且該插口還沒有綁定。不能兩次綁定一個插口。6 8 - 7 1這個if語句有點令人疑問。總的結果是如果SO_REUSEADDR和SO_REUSEPORT都沒有置位,就把wild設置成INPLOOKUP_WILDCARD。對UDP來說,第二個測試為真,因為 PR_CONNREQUIRED對無連接插口為假,對面向連接的插口為真。第三個測試就是疑問所在 Torek 1992 。插口標志 S O _ A C C E P T C O N N只被系統調用 listen置位(15.9節),該值只對面向連接的服務器有效。在正常情況下,一個 TCP服務器調用soc

47、ket、bind,然后調用listen。因而,當in_pcbbind被bind調用時,就清除了這個插口標志位。即使進程調用完 s o c k e t 后就調用 l i s t e n ,而不調用 b i n d , T C P的 PRU_LISTEN請求還是調用in_pcbbind,在插口層設置SO_ACCEPTCONN標志位之前,給插口分配一個臨時端口。這意味著 if語句中的第三個測試,測試SO_ACCEPTCONN是否沒有置位,總是為真。因此if語句等價于if (so-so_options & (SO_REUSEADDR|SO_REUSEPORT) = 0 & (so-so_proto-p

48、r_flags & PR_CONNREQUIRED)=0|1)wild = INPLOOKUP_WILDCARD;因為任何與1作邏輯或運算的結果都為真,所以這等價于if (so-so_options & (SO_REUSEADDR|SO_REUSEPORT) = 0 ) wild = INPLOOKUP_WILDCARD;這樣簡單且容易理解:如果任何一個 REUSE插口選項被置位, wild就是0。如果沒有 REUSE選項被置位,則把wild設成INPLOOKUP_WILDCARD。換言之,當函數在后面調用 in_pcblookup時,只有在沒有REUSE選項處于開狀態時,才允許通配匹配。58

49、6計計TCP/IP詳解 卷2:實現in_pcbbind的下一部分,顯示在圖22-22中,函數處理可選nam參數。7 2 - 7 5只有當進程顯式調用 bind時, nam參數才是一個非零指針。對一個隱式的綁定(connect、listen或in_pcbconnect的副作用,本節開始的情形 3、4和5),nam是一個空指針。當指定了該參數時,它是一個含有 sockaddr_in結構的mbuf。圖22-21顯示了非空參數nam的四種情形。圖22-21 in_pcbbind 的nam 參數的四種情形對正確的地址族的測試被注釋掉了,但在函數 in_pcbconnect(圖22-25)中執行了7 6

50、- 8 3等價的測試。希望兩者或者都有或者都沒有。8 5 - 9 4Net/3測試被綁定的IP地址是否是一個多播組。如果是,則SO_REUSEADDR選項被認為與SO_REUSEPORT等價。9 5 - 9 9否則,如果調用方綁定的本地地址不是通配地址,則 ifa_ifwi與一個本地接口對應。ddr驗證該地址注釋“ y e c h ”可能是因為插口地址結構中的端必須是0 ,因為 i f a _ifwiddr對整個結構作二進制比較,而不僅僅比較 IP地址。這是進程在調用系統調用之前必須把插口地址結構全部置零的幾種情況之一。如果調用 b i n d ,并且插口地址結構 ( s i n _ z e

51、r o 8 ) 的最后 8 個字節非零,則ifa_ifwiddr將找不到請求的接口, in_pcbbind會返回一個錯誤。1 0 0 - 1 0 5當調用方綁定了一個非零端口時,也就是說,進程要綁定一個特殊端(圖22-2 1 中 的 第 2 種 和 第 4 種 情 形 ) , 就 執 行 下 一 個 i f 語 句 。 如 果 請 求 的 端 口 小 于1024(IPPORT_部分,而是),則進程必須具有超級用戶的優先權限。這不是ernet協議的一port),例的。使用小于 1024的端,稱之為保留端口 (如,rcmd函數 Stevens 1990使用的端口, rlogin和rsh客戶程序又調

52、用該函數,作為服務器對它們認證的一部分。1 0 6 - 1 0 9然后調用函數in_pcblookup(圖22-16),檢測是否已經存在一個具有相同本地IP地址和本地端端(外部端的PCB。第二個參數是通配IP地址(外部IP地址),第三個參數是一個為 0的)。第二個參數的通配值導致 in_pcblookup忽略該PCB的外部IP地址和外部端口 只把本地IP 地址和本地端分別和sin-sin_addr及lport進行比較。我們 前 面 提 到 , 只 有 當 所 有 R E U S E 插 口 選 項 都 沒 有 被 設 置 時 , 才 把 w i l d 設 成INPLOOKUP_WILDCAR

53、D。1 1 1 調用方的本地IP地址值存放在PCB中。如果調用方指定,它可以是通配地址。在這種情況下,由內核選擇本地 IP地址,但要等到晚些時候插口連接上時。這就是為什么說本地 IP地址是根據外部IP地址,由IP路由選擇決定。nam參數PCB成員被設成:說明localIPlportinp_laddrinp_iport不是*不是*0非零0非零localIP localIP*臨時端口lport臨時端口lportlocalIP必須是本地接口交付給in_pcblookup交付給 in_pcblookup第 22 章 協議控制塊計計587圖22-22 in_pcbbind 函數:處理可選的nam 參數當

54、調用式綁定端口 0,或nam參數是一個空指針(隱式綁定)時,in_pcbbind的最后一部分處理分配一個臨時端口。1 1 3 - 1 2 2 這個協議(TCP或UDP)使用的下一個臨時端被在該協議的 PCB表的head:tcb或udb。除了協議的he唯一被使用的元素是本地端CB中的inp_next和inp_back指針外, ib結構另一個。令人迷惑的是,這個本地端口在heCB中是主機字節序,而 在 表 中 其 他 P C B 上 , 卻 是 網 絡 字 節 序 ! 使 用 從 1 0 2 4 開 始 的 臨 時 端(IPPORT_),每次加1,直到5000(IPPORT_USER),然后又從1

55、024重新開始循環。該循環一直執行到in_pcbbind找不到匹配為止。1. SO_REUSEADDR舉例讓通過一些普通的例子,來了解一下 in_pcbbind與in_pcblookup及兩個REUSE588計計TCP/IP詳解 卷2:實現插口選項之間的交互。圖22-23 in_pcbbind 函數:選擇一個臨時端口TCP或UDP通常以調用socket和bind開始。假定一個調用bind的TCP服務器,指定了通配IP 地址和它的非零知名端口 23( net服務器)。還假定該服務器還沒有運行,進程沒有設置SO_REUSEADDR插口選項。in_pcbbind把INPLOOKUP_WILDCARD

56、作為最后一個參數,調用in_pcblookup。 in_pcblookup中的循環沒有找到匹配的PCB,就假定沒有其他進程使用服務器的知名TCP端口,返回一個空指針。一切正常, in_pcbbind,返回0。假定和上面相同的情況,但當再次試圖啟動服務器時,該服務器已經開始運行。當調用in_pcblookup時,它發現了本地插口為*, 23的PCB。因為wildcard計數器是0,所以in_pcblookup返回指向這個in_pcbbind返回EADDRINUSE。的指針。因為 reuseport是0,所以3) 假定與上面相同的情況,但當第二次試圖啟動服務器時,指定了 SO_REUSEADDR插

57、口選項。因為指定了這個插口選項,所以in_pcbbind在調用in_pcblookup時,最后一個參數為0。但本地插口為*, 23的PCB仍然匹配,因為in_pcblookup無法比較兩個通配地址(圖22-17),所以wildcard為0。in_pcbbind又返回EADDRINUSE,避免啟動兩個具有相同本地插口的服務器例程,不管是否指定了 SO_REUSEADDR。4) 假定有一個net服務器已經以本地插口 *, 23 開始運行,而試圖以另一個本地插口140.252.13.35,23啟動另一個服務器。假定沒有指定 S O _ R E U S E A D D R ,調用 i n _ p c

58、b l o o k u p 時,最后一個參數為 INPLOOKUP_WILDCARD。當它與含有*.23的PCB比較時,wildcard計數器被設為1。因為允許通配匹配,所以在掃描完所有 TCP PCB 后,就把這個匹配作為最佳匹配。 in_pcbbind返回EADDRINUSE。5) 這個例子與上一個相同,但為第二個試圖綁定本地插口 140.252.13.35, 23的服務器指定了SO_REUSEADDR插口選項。現在, in_pcblookup的最后一個參數是 0,因為指定了插口選項。當與本地插口為*, 23的PCB比較時, wildcard計數器為1,但因為最后的flags參數是0,所以

59、跳過這個,不把它記作匹配。在比較完所有 TCP PCB 后,函數返回一個空指針,in_pcbbind返回0。第 22 章 協議控制塊計計5896) 假定當試圖以本地插口*, 23 啟動第二個服務器時,第一個net服務器以本地插口140.252.13.35, 23啟動。與前面的例子一樣,但這一次以相反的順序啟動服務器。第一個服務器的啟動沒有問題,假定沒有其他插口綁定到端口 23。當啟動第二個服務器時, in_pcblookup的最后一個參數是INPLOOKUP_WILDCARD,假定沒有指定SO_REUSEADDR插口選項。當和具有本地插口 140.252.13.35, 23 的PCB比較時,w

60、ildcard被設成1,這個。在比較完所有TCP PCB后,返回指向這個的指針。導致in_pcbbind返回EADDRINUSE。7) 如果況?假定啟動同一個服務器的兩個例程,并且都是非通配本地 IP地址,會發生什么情以本地插口140.252.13.35, 23 啟動第一個net服務器,然后試圖用本地插口127.0.0.1, 23啟動第二個服務器,且不指定SO_REUSEADDR。當第二個服務器調用 in_pcbbind時,它調用in_pcblookup,最后一個參數是 INPLOOKUP_WILDCARD。當比較具有本地插口140.252.13.35, 23的PCB時,因為本地 IP地址不相

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論