繼上篇
TCP/IP FAQ(1),本篇涵蓋了域和協(xié)議、IP編址、插口、原始IP、unix域方面的問題與解答。
【Domain & Protocol】
1. 什么是域,它和協(xié)議有什么關(guān)系?
域可以理解為一種容納協(xié)議的空間,它的存在便于了協(xié)議的分類;域和協(xié)議是集合與元素的關(guān)系,一個域中的每個協(xié)議使用同類地址,并且每種地址只被一個域使用,一個域能由協(xié)議族或地址族常量唯一標(biāo)識。
2. TCP/IP中有哪些域及其協(xié)議?
internet、iso、route、ccitt、imp、network systems和unix,其中internet域含有ip,icmp,igmp,tcp和udp五種協(xié)議,unix域用于ipc通信。
3. 哪些地方會用到域?
一個網(wǎng)絡(luò)層協(xié)議必須分用輸入數(shù)據(jù)報,并交給相應(yīng)的傳輸層協(xié)議,由于域包含了協(xié)議族,因此必須從對應(yīng)的域中找到合適的協(xié)議去處理。例如IP對應(yīng)的域?yàn)閕nternet,這個域?qū)?yīng)的協(xié)議族為inetsw,當(dāng)收到IP數(shù)據(jù)報時,就從inetsw中找到對應(yīng)的傳輸層協(xié)議去輸入處理。
【IP Addressing】
1. IP地址有哪幾類?
分為5類,A、B和C類用于單播;D類用于多播;E類用于實(shí)驗(yàn)。
2. sockaddr和sockaddr_in有什么區(qū)別聯(lián)系?
sockaddr是一種通用的用于接口編址信息的結(jié)構(gòu),它將硬件與協(xié)議的地址細(xì)節(jié)相對于接口層隱藏起來,成員依次為sa_len、sa_family和sa_data,而sockaddr_in成員依次為sin_len、sin_family、sin_port、sin_addr和sin_zero。它們的前兩個成員其實(shí)是一樣的,只是命名不同,而sockaddr_in中的sin_port標(biāo)識傳輸層的端口,sin_addr標(biāo)識IP層的地址,所以它是Internet協(xié)議的專用接口編址結(jié)構(gòu),sin_zero僅為填充用,因?yàn)閟ockaddr_in長度不應(yīng)小于sockaddr。
3. 插口編址結(jié)構(gòu)允許的最大長度是多少?
sockaddr最后一個成員是可擴(kuò)展的,這是C語言的通用技術(shù),因?yàn)槠涞谝粋€成員為u_char類型,所以最大長度是255。
4. 一個接口可以配置多個IP地址,是怎么實(shí)現(xiàn)的?
ifaddr表示通用的接口地址,ifnet表示接口,它有個類型為ifaddr*的if_addrlist成員,表示當(dāng)前接口上的地址鏈表。in_ifaddr表示Internet協(xié)議專用的接口地址,而IP屬于Internet協(xié)議,因此用in_ifaddr表示,所有的IP地址組成一個類型為in_ifaddr*的鏈表。當(dāng)增加一個IP地址時,就需要插入這兩個鏈表中;當(dāng)刪除一個IP地址時,就需要從它們當(dāng)中移除。
5. 為什么配置IP主機(jī)地址和網(wǎng)絡(luò)掩碼可以是獨(dú)立的?
因?yàn)樗鼈兪褂貌煌拿顚?shí)現(xiàn),前者用SIOCSIFADDR,后者用SIOCSIFNETMASK。當(dāng)配置IP主機(jī)地址時,如果沒有指明網(wǎng)絡(luò)掩碼,那么網(wǎng)絡(luò)掩碼被設(shè)置成默認(rèn)的。
6. 為什么訪問IP接口地址使用的是UDP插口而不是原始IP插口?
只有超級用戶用程才能創(chuàng)建原始IP插口,而通過UDP插口,任何用戶進(jìn)程都能查看接口配置。
【Socket】
1. 為什么會存在插口層?
從概念上講,tcp/ip協(xié)議棧劃分為鏈路、網(wǎng)絡(luò)、傳輸和應(yīng)用4層;但從實(shí)現(xiàn)上講,在應(yīng)用層和其下層中間,引入了一個插口層,作為進(jìn)程和內(nèi)核通信的橋梁,主要功能是將進(jìn)程發(fā)送的與協(xié)議有關(guān)的請求映射到產(chǎn)生插口時指定的與協(xié)議有關(guān)的實(shí)現(xiàn),從而屏蔽了不同協(xié)議處理的細(xì)節(jié)。
2. 為什么服務(wù)器進(jìn)程總是要調(diào)用bind,客戶進(jìn)程能調(diào)用它嗎?
bind將一個本地地址同一個插口相關(guān)聯(lián),客戶進(jìn)程需要同一個已知地址建立連接或發(fā)送數(shù)據(jù)報到已知地址,如果不調(diào)用bind,服務(wù)器進(jìn)程就無法在某個已知地址上接受TCP連接或接收UDP數(shù)據(jù)報。客戶進(jìn)程也能調(diào)用bind,這樣便可以由應(yīng)用程序而非內(nèi)核來選擇一個本地地址,其結(jié)果是只能接收目的地址為被綁定地址的數(shù)據(jù)包,但通常不必調(diào)用bind,因?yàn)閮?nèi)核會自動決定外出地址和臨時端口。
3. 對于tcp和udp協(xié)議的插口,調(diào)用connect有什么區(qū)別聯(lián)系?
共同點(diǎn)是設(shè)定插口的外部地址(插口的地址存儲在相關(guān)的協(xié)議控制塊中),不同點(diǎn)如下
1)tcp:與遠(yuǎn)端系統(tǒng)進(jìn)行3次握手交互,如果插口是非阻塞的且連接正在進(jìn)行中,那么返回EINPROGRESS,下次再調(diào)用則返回EALREADY;如果連接成功,無論是否阻塞,那么下次再調(diào)用會返回EISCONN;如果連接失敗,那么下次再調(diào)用,則重新開始三次握手。
2)udp:沒有3次握手交互,直接設(shè)定外部地址,無論插口是否阻塞,調(diào)用會立即返回,多次調(diào)用則會替換老的外部地址。發(fā)送數(shù)據(jù)必須使用write或目的地址為空的sendto,若sendto目的地址非空,則返回EISCONN。如果沒有事先調(diào)用connect,那么調(diào)用目的地址為空的sendto則會返回ENOTCONN。
4. 什么情況下調(diào)用close會阻塞?
連接已建立且設(shè)置了SO_LINGER選項(xiàng)并延時值非零的阻塞插口。
5. 插口IO有哪些系統(tǒng)調(diào)用?
發(fā)送有write、writev、sendto和sendmsg,接收有read、readv、recvfrom和recvmsg。注意,send和recv是庫函數(shù)而非系統(tǒng)調(diào)用,前者調(diào)用sendto實(shí)現(xiàn),后者調(diào)用recvfrom實(shí)現(xiàn)。
6. write、writev、read、readv與sendto、sendmsg、recvfrom、recvmsg有什么不同?
1)前面4個適合于任何描述符,而后面4個只能用于插口。
2)前面4個不支持標(biāo)志,而后面4個支持。
3)前面前2個不支持目的地址、后2個不支持源地址,而后面前2個支持目的地址、后2個支持源地址。
4)前面4個不支持控制信息,而后面第2個和第4個支持。
7. 如何斷開已連接的udp插口,允許調(diào)用sendto向其它主機(jī)發(fā)送數(shù)據(jù)?
由于系統(tǒng)并沒有提供形如disconnect的斷連API,但connect內(nèi)部實(shí)現(xiàn)是先斷連,再調(diào)用對應(yīng)協(xié)議的PRU_CONNECT請求處理,因此向connect傳遞無效的外部地址結(jié)構(gòu)(如IP=0.0.0.0,Port=0),雖然這樣會導(dǎo)致結(jié)果失敗,但先前的斷連成功,對應(yīng)pcb的外部地址被設(shè)為INADDR_ANY,所以調(diào)用sendto就不會返回EISCONN。
【Raw IP】
1. 怎么使用原始IP,它有哪些用途及應(yīng)用?
創(chuàng)建SOCK_RAW類型的原始插口,就能使用原始IP機(jī)制,它有下列用途:
1)發(fā)送和接收ICMP和IGMP報文,如ping程序和多播路由守護(hù)程序。
2)構(gòu)造自己的IP首部,如路由跟蹤程序。
3)設(shè)計(jì)基于IP的新的傳輸層協(xié)議,如gated程序。
2. 協(xié)議值為PROTOCOL_RAW(255)的原始插口能收到什么類型的IP數(shù)據(jù)報?
由于255是非零的保留值,這樣的IP數(shù)據(jù)報在網(wǎng)絡(luò)中不會存在,原始IP輸入處理協(xié)議比較測試失敗,因此收不到任何類型的IP數(shù)據(jù)報。
3. 協(xié)議值為0的原始插口能收到什么類型的IP數(shù)據(jù)報?
由于協(xié)議值為0,原始IP輸入處理忽略了協(xié)議比較測試,因此能收到任何類型的IP數(shù)據(jù)報。
4. 如何處理收到的IP數(shù)據(jù)報?
遍歷Internet PCB表,依次從協(xié)議值、本地地址和外部地址三項(xiàng)來比較IP數(shù)據(jù)報和每個PCB,將IP數(shù)據(jù)報復(fù)制追加到所有匹配的PCB對應(yīng)的插口緩存中,并喚醒等待的進(jìn)程。
5. 如何發(fā)送數(shù)據(jù)?
先填充IP首部,如果未設(shè)置IP_HDRINCL選項(xiàng),那么由內(nèi)核填充,否則由應(yīng)用程序在發(fā)送前填充,再交給IP協(xié)議輸出處理。
6. 內(nèi)核何時會調(diào)用原始輸入?
當(dāng)收到的協(xié)議類型為除IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP和IPPROTO_IGMP外的IP數(shù)據(jù)報時調(diào)用。
【Unix domain】
1. 使用unix域的原因有哪些?
1)當(dāng)通信雙方在同一主機(jī)上時,使用unix域插口的速度比tcp和udp插口要快很多。
2)支持同一主機(jī)進(jìn)程間傳遞描述符。
2. unix域和internet域有什么不同?
1)編址結(jié)構(gòu)不同:前者是sockaddr_un,與文件系統(tǒng)路徑名關(guān)聯(lián),而后者是sockaddr_in,與IP地址和端口關(guān)聯(lián)。
2)協(xié)議控制塊不同:前者是unpcb,沒有全局的pcb鏈表,而后者是inpcb,有全局的pcb雙向循環(huán)鏈表。
3. 如果一個unix域服務(wù)器在bind后unlink了被綁定的路徑名,會發(fā)生什么情況?
因?yàn)閏onnect內(nèi)部實(shí)現(xiàn)查找路徑名失敗,所以連接失敗,但listen會成功,因?yàn)閎ind會創(chuàng)建新的vnode和pcb關(guān)聯(lián),且PRU_LISTEN請求實(shí)現(xiàn)只檢查vnode是否為空。
4. 如果一個unix域服務(wù)器在終止時沒有unlink被綁定的路徑名,會發(fā)生什么情況?
因?yàn)閏onnect內(nèi)部實(shí)現(xiàn)雖能找到路徑名但找不到相關(guān)的插口,所以連接被拒絕。
5. 系統(tǒng)調(diào)用socketpair和pipe有什么區(qū)別聯(lián)系?
共同點(diǎn)是使用unix域,即socket調(diào)用第1參數(shù)為AF_UNIX,不同點(diǎn)如下
1)前者是雙工的,因?yàn)閮蓚€插口標(biāo)志都為讀寫,且它們的pcb相互指向?qū)Ψ剑缓笳呤菃喂さ模驗(yàn)橐粋€插口標(biāo)志為只讀,另一個為只寫,寫插口的pcb指向讀插口的pcb。
2)前者支持?jǐn)?shù)據(jù)報和流式插口,后者僅支持流式插口。
6. unix域是怎么實(shí)現(xiàn)傳遞描述符的?
描述符存儲在控制信息cmsghdr內(nèi),cms_level=SOL_SOCKET且cms_type=SCM_RIGHTS,unix域的發(fā)送請求實(shí)現(xiàn)將描述符轉(zhuǎn)換為file指針,這個過程叫內(nèi)部化,接收請求實(shí)現(xiàn)把file指針轉(zhuǎn)換為最小的沒有使用的描述符,這個過程叫外部化。
posted on 2013-09-03 15:52
春秋十二月 閱讀(2370)
評論(1) 編輯 收藏 引用 所屬分類:
Network