第十九章 APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)_第1頁
第十九章 APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)_第2頁
第十九章 APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)_第3頁
第十九章 APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)_第4頁
第十九章 APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第十九章APO連接與網(wǎng)絡(luò)v節(jié)點(diǎn)在編寫網(wǎng)絡(luò)底層實(shí)現(xiàn)前,需要做許多的準(zhǔn)備工作;除了修改前面的章節(jié)外,可能還需寫3章;本章、文件號(hào)管理類的實(shí)現(xiàn)、本地內(nèi)存管理類的實(shí)現(xiàn)。我很希望最終的網(wǎng)絡(luò)編程能給我驚喜;IP/TCP/UDP/ICMP的實(shí)現(xiàn)、包括所有的網(wǎng)絡(luò)服務(wù)器的實(shí)現(xiàn)(HTTP、DNS、FTP等等),能到達(dá)300行的代碼量;多于300行代碼量那就更好了、我會(huì)很高興。網(wǎng)絡(luò)編程第一層簡為socket層,第二層簡稱為TCP層,第三層簡稱為IP層;以后,不再說明。這章會(huì)寫得慢,因?yàn)橐屑?xì)的研究那個(gè):復(fù)雜的、巨大的、認(rèn)真的、嚴(yán)肅的、搞笑的、牛角尖的、牛逼的TCP協(xié)議。一、APO的連接什么是連接?這簡單的問題要耗費(fèi)我不少時(shí)間,簡單其實(shí)意味著復(fù)雜、是很多內(nèi)容濃縮而形成。Socket、插座、電話號(hào)碼、端口,就算我們通過類比來描述一個(gè)通信連接過程;但能完全描述一個(gè)連接嗎?對于一個(gè)socket客戶端口,確實(shí)對應(yīng)著一個(gè)客戶端連接。但對于同一個(gè)socket服務(wù)端口,可以有許多連接啊;顯然不行。使用雙方的IP地址、和socket端口來定義一個(gè)連接,那顯然可以;但那需要32字節(jié)啊,想快速定位一個(gè)連接是不行的。嗯、查了一下網(wǎng)上資料,天喲、真的是用什么5元組、7元組來確定一個(gè)連接!五元組是:源IP地址、目的IP地址、協(xié)議號(hào)、源端口、目的端口。七元組是:源IP地址、目的IP地址、協(xié)議號(hào)、源端口、目的端口,服務(wù)類型及接口索引。1、連接的表示

對于客戶端,可以用16位socket客戶端口來表示;那么、如何知道一個(gè)連接是客戶端還是服務(wù)端?我們需要建立一個(gè)端口表,并不大、因?yàn)橐粋€(gè)服務(wù)端口就對應(yīng)很多連接;APO的表大小只是8K項(xiàng)。那么、表項(xiàng)的內(nèi)容是什么?應(yīng)該是跟操作系統(tǒng)有關(guān),我不清楚,或許它們不是使用端口表來表示。不管怎樣,接收了一個(gè)數(shù)據(jù)包,就應(yīng)該判斷其屬于哪一個(gè)連接;想法與文件號(hào)sockfd關(guān)聯(lián)。APO的端口表項(xiàng)就是一個(gè)字,如果是客戶端口:高8位是狀態(tài)標(biāo)志、低24位是文件號(hào)sockfd;對于服務(wù)端口,高8位是狀態(tài)標(biāo)志、低24位是0;該端口項(xiàng)不用、全0。實(shí)際上,還需管理端口的位圖(用于端口的分配、釋放),及端口查詢表(表項(xiàng)內(nèi)容就是端口值)。提取IP數(shù)據(jù)包的目標(biāo)socket端口值,先在端口查詢表找出端口值在第i項(xiàng)(通常需要耗費(fèi)約30ns);之后、再用i去端口表獲得文件號(hào),如是0、則提取IP數(shù)據(jù)包的24位的服務(wù)端文件號(hào)字段。如果主機(jī)的MAC端口速度是1GBPS,包之間的最小間隔160ns;APO的最小包是512位、等效512ns;所以、在IP層處理一個(gè)IP數(shù)據(jù)包的最短時(shí)間只有672ns。IP層處理需要包含內(nèi)存管理、IP數(shù)據(jù)包組裝成IP數(shù)據(jù)報(bào)、錯(cuò)誤包處理、正確提交到TCP層(該層最復(fù)雜,連接、文件號(hào)管理、端口管理等,處理的最短時(shí)間只有672ns。)、ICMP報(bào)文處理等。APO的處理速度也就每秒1百多萬個(gè)數(shù)據(jù)包,支持千萬個(gè)連接應(yīng)該問題不大。使用五元組,目的方不是本機(jī)?三元組不行?嗯,它們不像APO主機(jī)是唯一的IP地址,是可以有多個(gè)IP地址。好了,五元組的字節(jié)數(shù)太多、直接比較耗費(fèi)太大(千個(gè)連接就會(huì)耗盡inte類主機(jī)資源),想法每元抽取8位、形成32位哈希值(哈希算法簡單、只抽取4元、夠啰嗦的)。那不一定是唯一哈希值啊,嗯、增加沖突處理;我要暈了!也許千個(gè)連接還行,對付10萬個(gè)連接時(shí),主機(jī)要歇菜。它們應(yīng)該是用鏈表去關(guān)聯(lián)到文件號(hào)sockfd,對于復(fù)雜腦袋型的操作系統(tǒng)、我無法進(jìn)行仔細(xì)探討,所以、只能是對它們推測。既然我們將socket看作文件,那么為何不直接使用文件號(hào)sockfd來代表一個(gè)連接呢?可以,APO就是這樣的??蛻舳司筒挥谜f了;在服務(wù)端,我們用不同的文件號(hào)來代表不同的客戶端到同一個(gè)服務(wù)端的連接;而描述連接的是文件號(hào)相對應(yīng)的內(nèi)存v節(jié)點(diǎn)。但客戶端是不知道它們到服務(wù)端的連接、在服務(wù)端的相應(yīng)文件號(hào)??;所以,需要在IP包中使用到24位的服務(wù)端文件號(hào)字段了。服務(wù)端文件號(hào)字段是服務(wù)端設(shè)置,而客戶端發(fā)送數(shù)據(jù)報(bào)時(shí)、也將服務(wù)端文件號(hào)字段一起轉(zhuǎn)發(fā)就行了。這樣,客戶端的數(shù)據(jù)報(bào)到達(dá)服務(wù)端主機(jī)的網(wǎng)絡(luò)底層時(shí),就可提取24位的服務(wù)端文件號(hào)字段、快速定位到相應(yīng)的內(nèi)存v節(jié)點(diǎn),從而得到該連接的描述。網(wǎng)絡(luò)底層通常是先提取數(shù)據(jù)包的目標(biāo)socket端口、查socket端口表,如是客戶端口,那就可以立即得到相應(yīng)的文件號(hào);如果是0(服務(wù)端口),那就需提取IP包頭的24位服務(wù)端文件號(hào)字段了;當(dāng)然、進(jìn)入相應(yīng)的v節(jié)點(diǎn)后,還需進(jìn)一步比較確認(rèn),那只是不到10ns的一次性比較吧。2、建立連接信令必須可靠,TCP是使用三次握手連接,為何?要保證“信令可靠”,就需要對一個(gè)信令數(shù)據(jù)包進(jìn)行ack確認(rèn)表示接收端收到。如果收不到ack,就要做超時(shí)重發(fā)、APO最多3次超時(shí)重發(fā)。在Linux下,默認(rèn)重試次數(shù)為5次,重試的間隔時(shí)間從1s開始每次都翻售,5次的重試時(shí)間間隔為1s,2s,4s,8s,16s總共31s,第5次發(fā)出后還要等32s都知道第5次也超時(shí)了,所以,總共需要63s,TCP才會(huì)斷開這個(gè)連接。我們知道一個(gè)512的信令包只是不到1us,就算路徑有100個(gè)中間路由交換機(jī)的存儲(chǔ)轉(zhuǎn)發(fā)會(huì)產(chǎn)生一定的時(shí)延,從A到達(dá)B也不會(huì)到1ms、來回2ms;為何需要重試時(shí)間間隔為多于1s呢?這不浪費(fèi)時(shí)間嗎?給黑客利用的機(jī)會(huì)?有點(diǎn)像脫褲子放屁喲?你可能說,如果server端接到了clien發(fā)的SYN后回了SYN-ACK后client就突然掉線了(或故意不發(fā)ACK、這概率更大),server端沒有收到client回來的ACK,那么,應(yīng)該給client端1分鐘、和重發(fā)5次的機(jī)會(huì)。要知道主機(jī)每秒處理1百萬個(gè)數(shù)據(jù)包,那么1分鐘就6千萬個(gè)數(shù)據(jù)包?。?/p>

如果這些數(shù)據(jù)包都是請求連接信令包、主機(jī)的資源就給耗盡。一些惡意的人就為此制造了SYNFlood攻一服務(wù)器發(fā)了一個(gè)SYN后,就下線了,于是服務(wù)器需要默認(rèn)等63s才會(huì)斷開連接;這樣,攻擊者就可以把服務(wù)器的syn連接的隊(duì)列耗盡,讓正常的連接請求不能處理。于是,為了糾正一個(gè)小錯(cuò)誤,就要付出更為復(fù)雜和耗時(shí)的代價(jià)。Linux下給了一個(gè)叫tcp_syncookies的參數(shù)來應(yīng)對這個(gè)事當(dāng)SYN隊(duì)列滿了后,TCP會(huì)通過源地址端口、目標(biāo)地址端口和時(shí)間戳打造出一個(gè)特別的SequenceNumber發(fā)回去(又叫cookie),如果是攻擊者則不會(huì)有響應(yīng),如果是正常連接,則會(huì)把這個(gè)SYNCookie發(fā)回來,然后服務(wù)端可以通過cookie建連接(即使你不在SYN隊(duì)列中)。代價(jià)就是,本可以每秒處理1百萬個(gè)數(shù)據(jù)包,可能變成每秒處理1萬個(gè)數(shù)據(jù)包。關(guān)于這些,linux還有不少的復(fù)雜處理方法;不再討論。我就想不通,為何復(fù)雜腦袋的產(chǎn)物總是九曲十八彎的;就不能簡明些;協(xié)議也不應(yīng)該是專為垃圾主機(jī)制定的。MSS是最大傳輸大小的縮寫,就是TCP數(shù)據(jù)包每次能夠傳輸?shù)淖畲髷?shù)據(jù)報(bào)分段。一個(gè)數(shù)據(jù)報(bào)被分段成多個(gè)小于MTU的數(shù)據(jù)包(也叫數(shù)據(jù)報(bào)分段)。為了達(dá)到最佳的傳輸效能TCP協(xié)議在建立連接的時(shí)候通常要協(xié)商雙方的MSS值,這個(gè)值TCP協(xié)議在實(shí)現(xiàn)的時(shí)候往往用MTU值代替(需要減去MAC頭18字節(jié)、IP數(shù)據(jù)包包頭的大小20Bytes和TCP數(shù)據(jù)段的包頭20Bytes)所以往往MSS為1518-58=1460B。通常MTU是1536B,而傳輸一個(gè)TCP信令只是64B,浪費(fèi)?。?次握手、還要探查MTU和協(xié)商MSS值、測試往返時(shí)間,你說要建立一個(gè)連接需要多少次信令報(bào)往返?浪費(fèi)多少資源?我以前遠(yuǎn)看TCP協(xié)議、感覺嚴(yán)謹(jǐn)、偉大,就像充滿迷一樣的大石山;為何、現(xiàn)在看上去就像垃圾山?漏洞百出、被黑客攻擊得遍體鱗傷,好搞笑?。⌒W(xué)生水平都不如,卻復(fù)雜無比、扁扁我還看幾天才略懂;誒、矛盾的世界。在APO中,TCP是雙工連接、UDP是簡單型半雙工連接。APO的連接并非是通常的TCP三次握手連接,而是使用ICMP探查數(shù)據(jù)包來進(jìn)行連接的;只是2次握手,請求、確

認(rèn)。當(dāng)客戶端的請求連接ICMP探查數(shù)據(jù)包到達(dá)服務(wù)端時(shí),探查數(shù)據(jù)包已經(jīng)包含了沿途路由交換機(jī)的MTU、時(shí)間戳、IP地址標(biāo)記等(共16字節(jié));那么、服務(wù)端就可知道請求方的地球位置、路徑信息、IP地址、單向耗時(shí),并做過濾分析:源IP地址、路由交換機(jī)的鏈路地址是否上了黑名單;如果安全,那么服務(wù)端建立描述該連接的文件號(hào)、保存連接描述到內(nèi)存v節(jié)點(diǎn),轉(zhuǎn)發(fā)ICMP探查數(shù)據(jù)包,并在上面打上服務(wù)端文件號(hào)字段、分段大小MSS、允許的數(shù)據(jù)報(bào)大小、單向耗時(shí)、ACK確認(rèn)等印記。APO網(wǎng)絡(luò)是無法假冒源地址的,除非你劫持了路由交換機(jī)的子網(wǎng)地址。但服務(wù)端規(guī)定了子網(wǎng)每秒發(fā)出到服務(wù)端的連接請求數(shù)不能超過1000個(gè)、主機(jī)每秒發(fā)出到服務(wù)端的連接請求數(shù)不能超過10個(gè);黑客想SYNFlood攻擊是不可能的,要知道服務(wù)端可是允許千萬個(gè)連接??;APO取消了廣播,你用組播服務(wù)器、還是相當(dāng)于從一臺(tái)機(jī)器發(fā)包,沒用。那么,劫持路由交換機(jī)的子網(wǎng)地址,每秒連接請求數(shù)1000個(gè),連續(xù)n秒;也沒用,APO的重發(fā)時(shí)間是1s、上一批的1000個(gè)連接,如果沒發(fā)數(shù)據(jù)包、就被取消了連接。黑客啊,千萬別上黑名單,否則來多少數(shù)據(jù)包、就被丟掉還是小事;事后、追究、報(bào)警才大件事。那么,使用招數(shù):占著茅坑不拉屎;臺(tái)主機(jī)正常連接、每10分鐘發(fā)一個(gè)垃圾GET請求來保持連接。這也不行,服務(wù)端規(guī)定每臺(tái)主機(jī)只給50個(gè)連接;黑客需要劫持30多萬臺(tái)主機(jī)。如果主機(jī)用APO操作系統(tǒng),你想劫持那么多主機(jī)的root、只是做夢。APO信令報(bào)文只是最多發(fā)3次,重發(fā)時(shí)間間隔是,200ms、600ms,延遲到1s時(shí)、如果沒收到ACK(客戶端)或數(shù)據(jù)包(服務(wù)端)、就釋放了該連接。APO的探查ICMP數(shù)據(jù)包最多45E,只能最多90個(gè)路由交換機(jī)的印記;如果往返超過90個(gè),那么會(huì)有部分印記被消除。使用匯聚路由交換機(jī),這種情形不會(huì)出現(xiàn),再遠(yuǎn)、往返也不會(huì)超過50個(gè)路由交換機(jī)。客戶端發(fā)送SYN連接請求ICMP探查數(shù)據(jù)包后、進(jìn)入SYN_SENT狀態(tài)。服務(wù)端收到連接請求ICMP探查數(shù)據(jù)包后、轉(zhuǎn)發(fā)打上印記ACK+SYN的ICMP探查數(shù)據(jù)包、進(jìn)入SYN_RECEIVED狀態(tài);如果在1s內(nèi)、再次收到相應(yīng)客戶端的IP數(shù)據(jù)包,則進(jìn)入ESTABLISHED連接建立狀態(tài)。否則、在1s內(nèi)重發(fā)2次后,沒收到數(shù)據(jù)包;釋放該連接!客戶端收到確

認(rèn)ICMP探查數(shù)據(jù)包后,才確認(rèn)該連接、進(jìn)入ESTABLISHED狀態(tài),并計(jì)算往返時(shí)間、確定MSS、初始化發(fā)送數(shù)據(jù)報(bào)的頭;發(fā)送第一個(gè)IP數(shù)據(jù)包。如果收到如目標(biāo)不可到達(dá)等的ICMP差錯(cuò)報(bào)文,釋放連接、返回錯(cuò)誤消息給應(yīng)用層。如果、超時(shí)則重發(fā)最多2次的請求連接ICMP探查數(shù)據(jù)包;如果在1s內(nèi)沒收到服務(wù)端的確認(rèn)ICMP探查數(shù)據(jù)包,則釋放連接、返回錯(cuò)誤消息給應(yīng)用層。3、連接建立后的TCP通信TCP要保證所有的數(shù)據(jù)包都可以到達(dá),所以,必需要有重傳機(jī)制。假如客戶端只是請求下載一個(gè)大小32GB的文件,TCP先是分割成512K個(gè)64KB的報(bào)文、再將每個(gè)報(bào)文分段成、比如1280B的52個(gè)IP數(shù)據(jù)包吧。我們假設(shè)一個(gè)IP數(shù)據(jù)包的往返時(shí)間是2ms,如果每發(fā)送一個(gè)IP數(shù)據(jù)包、都要來一個(gè)確認(rèn)后,才發(fā)下一個(gè)數(shù)據(jù)包,那要暈倒!不說,ACK信令包浪費(fèi)帶寬,可是要多花2倍的時(shí)間啊,學(xué)院派的大神們、終于臉紅了,羞愧了。還有啊,如果對方?jīng)]有ACK回應(yīng)、那還要等待超時(shí)重發(fā),還要慘。TCP每發(fā)送一個(gè)報(bào)文段,就對此報(bào)文段設(shè)置一個(gè)超時(shí)重傳計(jì)時(shí)器。此計(jì)時(shí)器設(shè)置的超時(shí)重傳時(shí)間RTO(RetransmissionTime—Out)應(yīng)當(dāng)略大于TCP報(bào)文段的平均往返時(shí)延日隊(duì),一般可取RTO=2RTT;4ms?但是,也可以根據(jù)具體情況人為調(diào)整RTO的值,例如可以設(shè)置此超時(shí)重傳時(shí)間RTO=90秒。當(dāng)超過了規(guī)定的超時(shí)重傳時(shí)間還未收到對此TCP報(bào)文段的預(yù)期確認(rèn)信息,則必須重新傳輸此TCP報(bào)文段。重傳計(jì)時(shí)器(retransmissiontimer):當(dāng)TCP發(fā)送報(bào)文段時(shí),就創(chuàng)建該特定報(bào)文段的重傳計(jì)時(shí)器??赡馨l(fā)生兩種情況:A:若在計(jì)時(shí)器截止時(shí)間到(通常是60秒)之前收到了對此特定報(bào)文段的確認(rèn),則撤銷此計(jì)時(shí)器。B:若在收到了對此特定報(bào)文段的確認(rèn)之前計(jì)時(shí)器截止期到,則重傳此報(bào)文段,并將計(jì)時(shí)器復(fù)位。

TCP在重發(fā)的時(shí)候不是等間隔的,第一次和第二次發(fā)送之間是N秒,第二次和第三次之間是2N秒,一般N的初值是6秒吧,75秒內(nèi)收不到回應(yīng)TCP層就認(rèn)為連接失敗(不同的系統(tǒng)可能這個(gè)值不同),這些值可能都是無法控制的,TCP自己有一套復(fù)雜的RTT測量算法,重發(fā)間隔就是基于這個(gè)算法;忽快忽慢應(yīng)該和重發(fā)的不等間隔性質(zhì)有關(guān)。以上的幾段是網(wǎng)上摘抄,我到現(xiàn)在都不明白具體的重傳時(shí)間!即使是6秒啊,那也可以發(fā)送好幾百萬個(gè)數(shù)據(jù)包了;學(xué)院派啊、真是不惜成本。下面是網(wǎng)上摘抄TCP的RTT算法。從前面的TCP的重傳機(jī)制我們知道Timeout的設(shè)置對于重傳非常重要,設(shè)長了,重發(fā)就慢,沒有效率,性能差;設(shè)短了,重發(fā)的就快,會(huì)增加網(wǎng)絡(luò)擁塞,導(dǎo)致更多的超時(shí),更多的超時(shí)導(dǎo)致更多的重發(fā)。而且,這個(gè)超時(shí)時(shí)間在不同的網(wǎng)絡(luò)的情況下,有不同的時(shí)間,根本沒有辦法設(shè)置一個(gè)死的。只能動(dòng)態(tài)地設(shè)置。為了動(dòng)態(tài)地設(shè)置,TCP引入了RTT——RoundTripTime,也就是一個(gè)數(shù)據(jù)包從發(fā)出去到回來的時(shí)間。這樣發(fā)送端就大約知道需要多少的時(shí)間,從而可以方便地設(shè)置TimeoutRTO(RetransmissionTimeOut),以讓我們的重傳機(jī)制更高效。聽起來似乎很簡單,好像就是在發(fā)送端發(fā)包時(shí)記下t0,然后接收端再把這個(gè)ack回來時(shí)再記一個(gè)七1,于是RTT=t1-t0。沒那么簡單,這只是一個(gè)采樣,不能代表普遍情況。經(jīng)典算法:1)首先,先采樣日頂,記下最近好幾次的RTT值。2)然后做平滑計(jì)算SRTT-SmoothedRTT。公式為:(其中的a取值在0.8到0.9之間,這個(gè)算法英文叫Exponentialweightedmovingaverage中文叫:加權(quán)移動(dòng)平均)SRTT=(a*SRTT)+((1-a)*RTT)3)開始計(jì)算RTO。公式如下:RTO=min[UBOUND,max[LBOUND,

(B*SRTT)]]其中:UBOUND是最大的timeout時(shí)間,上限值LBOUND是最小的timeout時(shí)間,下限值B值一般在1.3到2.0之間。Karn/Partridge算法:但是上面的這個(gè)算法在重傳的時(shí)候會(huì)出有一個(gè)終極問題一一>是用第一次的時(shí)間和ack回來的時(shí)候做RTT樣本,還是用重傳的時(shí)間和ACK的時(shí)間做RTT樣本?這個(gè)問題無論你先那頭都是按下葫蘆起了瓢。情況(a)是ack沒回來,所發(fā)重傳。如果你計(jì)算第一次發(fā)送和ACK的時(shí)間,那么,明顯算大了。情況(b)是ack回來慢了,重傳不一會(huì),之前ACK就回來了。如果你是算重傳的時(shí)間和ACK回來的時(shí)間,就會(huì)短了。Karn/PartridgeAlgorithm:這個(gè)算法的最大特點(diǎn)是忽略重傳,不把重傳的RTT做采樣(你看,你不需要去解決不存在的問題)。但是,這樣一來,又會(huì)引發(fā)一個(gè)大BUG——如果在某一時(shí)間,網(wǎng)絡(luò)閃動(dòng),突然變慢了,產(chǎn)生了比較大的延時(shí),這個(gè)延時(shí)導(dǎo)致要重轉(zhuǎn)所有的包(因?yàn)橹暗腞TO很?。?,于是,因?yàn)橹剞D(zhuǎn)的不算,所以,RTO就不會(huì)被更新,這是一個(gè)災(zāi)難。于是Karn算法用了一個(gè)取巧的方式——只要一發(fā)生重傳,就對現(xiàn)有的RTO值翻倍(這就是所謂的Exponentialbackoff)。Jacobson/Karels算法:前面兩種算法用的都是“加權(quán)移動(dòng)平均”,這種方法最大的毛病就是如果RTT有一個(gè)大的波動(dòng)的話,很難被發(fā)現(xiàn),因?yàn)楸黄交袅?。所以?988年,又有人推出來了一個(gè)新的算法,這個(gè)算法叫Jacobson/KarelsAlgorithm。這個(gè)算法引入了最新的RTT的采樣和平滑過的SRTT的差距做因子來計(jì)算。公式如下:(其中的DevRTT是DeviationRTT的意思)SRTT=SRTT+a(RTT-SRTT)DevRTT=(1-p)*DevRTT+B*(|RTT-SRTT|)RTO=四

*SRTT+d*DevRTT(其中:在Linux下,a=0.125,。=0.25,p=1,d=4——這就是算法中的“調(diào)得一手好參數(shù)”,nobodyknowswhy,itjustworks…)最后的這個(gè)算法在被用在今天的TCP協(xié)議中。我真的暈倒了,那要耗去多少CPU資源?。恳獮橹帉懚嗌俅a???能支持到1萬個(gè)連接嗎?你們的腦袋何必那樣復(fù)雜???要知道過了、就成腦殘??!嗯,重傳機(jī)制、羞愧的學(xué)院派大神們、開始改進(jìn)了;我們往下看,他們?nèi)绾巫?。接收端給發(fā)送端的Ack確認(rèn)只會(huì)確認(rèn)最后一個(gè)連續(xù)的包,比如,發(fā)送端發(fā)了1,2,3,4,5一共五份數(shù)據(jù),接收端收到了1,2,于是回ack3,然后收到了4(注意此時(shí)3沒收到),此時(shí)的TCP會(huì)怎么辦?我們要知道,SeqNum和Ack是以字節(jié)數(shù)為單位,所以ack的時(shí)候,不能跳著確認(rèn),只能確認(rèn)最大的連續(xù)收到的包,不然,發(fā)送端就以為之前的都收到了。一種是不回ack,死等3,當(dāng)發(fā)送方發(fā)現(xiàn)收不到3的ack超時(shí)后,會(huì)重傳3。一旦接收方收到3后,會(huì)ack回4——意味著3和4都收到了。但是,這種方式會(huì)有比較嚴(yán)重的問題,那就是因?yàn)橐赖?,所以會(huì)導(dǎo)致4和5即便已經(jīng)收到了,而發(fā)送方也完全不知道發(fā)生了什么事,因?yàn)闆]有收到Ack,所以,發(fā)送方可能會(huì)悲觀地認(rèn)為也丟了,所以有可能也會(huì)導(dǎo)致4和5的重傳。對此有兩種選擇:一種是僅重傳timeout的包,也就是第3份數(shù)據(jù)。另一種是重傳timeout后所有的數(shù)據(jù),也就是第3,4,5這三份數(shù)據(jù)。這兩種方式有好也有不好。第一種會(huì)節(jié)省帶寬,但是慢,第二種會(huì)快一點(diǎn),但是會(huì)浪費(fèi)帶寬,也可能會(huì)有無用功。但總體來說都不好。因?yàn)槎荚诘萾imeout,timeout可能會(huì)很長。

于是,TCP引入了一種叫FastRetransmit的算法,不以時(shí)間驅(qū)動(dòng),而以數(shù)據(jù)驅(qū)動(dòng)重傳。也就是說,如果,包沒有連續(xù)到達(dá),就ack最后那個(gè)可能被丟了的包,如果發(fā)送方連續(xù)收到3次相同的ack,就重傳。FastRetransmit的好處是不用等timeout了再重傳。比如:如果發(fā)送方發(fā)出了1,2,3,4,5份數(shù)據(jù),第一份先到送了,于是就ack回2,結(jié)果2因?yàn)槟承┰驔]收到,3到達(dá)了,于是還是ack回2,后面的4和5都到了,但是還是ack回2,因?yàn)?還是沒有收到,于是發(fā)送端收到了三個(gè)ack=2的確認(rèn),知道了2還沒有到,于是就馬上重傳2。然后,接收端收到了2,此時(shí)因?yàn)?,4,5都收到了,于是ack回6。FastRetransmit只解決了一個(gè)問題,就是timeout的問題,它依然面臨一個(gè)艱難的選擇,就是重傳之前的一個(gè)還是重裝所有的問題。對于上面的示例來說,是重傳#2呢?還是重傳#2,#3,#4,#5呢?因?yàn)榘l(fā)送端并不清楚這連續(xù)的3個(gè)ack(2)是誰傳回來的?也許發(fā)送端發(fā)了20份數(shù)據(jù),是#6,#10,#20傳來的呢。這樣,發(fā)送端很有可能要重傳從2到20的這堆數(shù)據(jù)(這就是某些TCP的實(shí)際的實(shí)現(xiàn));可見,這是一把雙刃劍。另外一種更好的方式叫:SelectiveAcknowledgment(SACK),這種方式需要在TCP頭里加一個(gè)SACK的東西,ACK還是FastRetransmit的ACK,SACK則是匯報(bào)收到的數(shù)據(jù)碎版。這樣,在發(fā)送端就可以根據(jù)回傳的SACK來知道哪些數(shù)據(jù)到了,哪些沒有到。于是就優(yōu)化了FastRetransmit的算法。當(dāng)然,這個(gè)協(xié)議需要兩邊都支持。在Linux下,可以通過tcp_sack參數(shù)打開這個(gè)功能。這里還需要注意一個(gè)問題收方Reneging,所謂Reneging的意思就是接收方有權(quán)把已經(jīng)報(bào)給發(fā)送端SACK里的數(shù)據(jù)給丟了。這樣干是不被鼓勵(lì)的,因?yàn)檫@個(gè)事會(huì)把問題復(fù)雜化了,但是,接收方這么做可能會(huì)有些極端情況,比如要把內(nèi)存給別的更重要的東西。所以,發(fā)送方也不能完全依賴SACK,還是要依賴ACK,并維護(hù)Time-Out,如果后

續(xù)的ACK沒有增長,那么還是要把SACK的東西重傳,另外,接收端這邊永遠(yuǎn)不能把SACK的包標(biāo)記為Ack。注意:SACK會(huì)消費(fèi)發(fā)送方的資源,試想,如果一個(gè)攻擊者給數(shù)據(jù)發(fā)送方發(fā)一堆SACK的選項(xiàng),這會(huì)導(dǎo)致發(fā)送方開始要重傳甚至遍歷已經(jīng)發(fā)出的數(shù)據(jù),這會(huì)消耗很多發(fā)送端的資源。DuplicateSACK又稱D-SACK,其主要使用了SACK來告訴發(fā)送方有哪些數(shù)據(jù)被重復(fù)接收了。D-SACK使用了SACK的第一個(gè)段來做標(biāo)志,如果SACK的第一個(gè)段的范圍被ACK所覆蓋,那么就是D-SACK。如果SACK的第一個(gè)段的范圍被SACK的第二個(gè)段覆蓋,那么就是D-SACK。引入了D-SACK,有這么幾個(gè)好處:1)可以讓發(fā)送方知道,是發(fā)出去的包丟了,還是回來的ACK包丟了。2)是不是自己的timeout太小了,導(dǎo)致重傳。3)網(wǎng)絡(luò)上出現(xiàn)了先發(fā)的包后到的情況(又稱reordering)4)網(wǎng)絡(luò)上是不是把我的數(shù)據(jù)包給復(fù)制了。知道這些東西可以很好得幫助TCP了解網(wǎng)絡(luò)情況,從而可以更好的做網(wǎng)絡(luò)上的流控;Linux下的tcp_dsack參數(shù)用于開啟這個(gè)功能。暈了吧!如果為了掩蓋一個(gè)小小的謊言,可以使用更復(fù)雜的、更大的謊言;為了糾正一個(gè)小小錯(cuò)誤,可以犯更大的錯(cuò)誤、使用更為復(fù)雜的犯錯(cuò)方式的話。如果這成為真理、成為聰明人之常情的話;我無語、佩服得五體投地。有更為簡潔的!要在IP層的實(shí)現(xiàn)那章才介紹。大神們,你們就不能簡單的去思考?據(jù)說,如果你不了解TCP的滑動(dòng)窗口這個(gè)事,你等于不了解TCP協(xié)議。那為何不將其想象成一堆臃腫垃圾?我正是這樣,所以也不想深入的去理解!有關(guān)滑動(dòng)窗口的事情、可以寫成一本書了。當(dāng)紅臉叫獸得意非凡的吹噓“交通規(guī)則、糊涂窗口、小包傳輸”時(shí),

我看到的是巨大的代碼量、和低能的效率、少量的連接!蒼白搞笑的吹噓,我體起疙瘩、渾身無力;是那樣的無奈。大神們,別搞了;求你們了,我真的受不了。我不生氣、我不生氣!“牢騷太盛防腸斷,風(fēng)物長宜放眼量?!蔽野還不行?4、連接的斷開在APO中,連接的斷開是簡單的、也沒有那么多種狀態(tài),也沒有什么4次握手的概念。主動(dòng)關(guān)閉(activeclose)端應(yīng)用程序調(diào)用close,于是其TCP層發(fā)出FIN請求主動(dòng)關(guān)閉連接,之后進(jìn)入FIN_WAIT狀態(tài);等待遠(yuǎn)程TCP的ACK確認(rèn),收到ACK則釋放連接。如果1s內(nèi)、并重發(fā)2次FIN請求,還是沒有收到ACK;也釋放連接。被動(dòng)關(guān)閉(passiveclose)端TCP也是類似的;當(dāng)被動(dòng)關(guān)閉端TCP接到FIN后,就發(fā)出ACK以回應(yīng)FIN請求(它的接收也作為文件結(jié)束符傳遞給上層應(yīng)用程序),并進(jìn)入TIME-WAIT:等待足夠的時(shí)間(1s內(nèi)、如果再次收到FIN,會(huì)重發(fā)ACK;最多2次),以確保遠(yuǎn)程TCP接收到連接斷開請求的確認(rèn)ACK。不管怎樣,在1s后,都會(huì)自動(dòng)釋放被動(dòng)關(guān)閉端的連接。TIME_WAIT等待狀態(tài),又叫做2MSL狀態(tài)。APO的服務(wù)端的多個(gè)客戶連接、是TCP層實(shí)現(xiàn)的,每秒可實(shí)現(xiàn)上百萬個(gè)連接;跟應(yīng)用層無關(guān),不需要那些listen()、accept()、connect()等垃圾。無須像流行TCP那樣,應(yīng)用程序在2MSL時(shí)間內(nèi)是無法再次使用同一個(gè)插口的,啟動(dòng)httpd就會(huì)出現(xiàn)錯(cuò)誤(插口被使用),也沒有服務(wù)器平靜時(shí)間的概念。在關(guān)閉連接后,也許該連接還有一些數(shù)據(jù)包在網(wǎng)絡(luò)中傳輸;但1s內(nèi)應(yīng)該都被IP層判斷無此連接而丟棄了,如果剛好新連接參數(shù)(客戶端口、IP地址)與舊連接的一樣、并收到這些遺留數(shù)據(jù)包,那會(huì)怎樣?我們是否能用流標(biāo)簽去判斷、從而丟棄?還是其它方法?我們還應(yīng)考慮下極端情形:假如一個(gè)客戶端A,和服務(wù)端B建立了一個(gè)連接。如果A

關(guān)閉了連接,或許根本就不發(fā)FIN,或許發(fā)送了FIN、而B喝醉酒不響應(yīng),或許FIN丟失,或許B發(fā)了入庭、而A沒收到超時(shí)關(guān)閉;總之是A關(guān)閉了、B可能還是在ESTABLISHED狀態(tài)。如果客戶端A重復(fù)的上演這種情況,那么服務(wù)端B將會(huì)出現(xiàn)大量的虛假的ESTABLISHED連接。如何解決?我們是否應(yīng)該在協(xié)議上增加一個(gè)由服務(wù)器定義的隨機(jī)的32位唯一標(biāo)識(shí)字段?或者這是否就可以用服務(wù)端sockfd文件號(hào)字段表示呢?這樣一來,客戶端的連接,肯定是對應(yīng)著唯一的服務(wù)端sockfd文件號(hào)字段;如果,服務(wù)端向客戶端發(fā)出查詢一個(gè)連接是否真實(shí)存在時(shí),客戶端就可拿端口對應(yīng)的v節(jié)點(diǎn)內(nèi)的服務(wù)端sockfd文件號(hào)字段與數(shù)據(jù)包的做比對;不一樣,那就返回虛假連接ACK應(yīng)答了;服務(wù)端就可以釋放虛假連接。那么,我們對于遺留數(shù)據(jù)包也同樣處理、從而丟棄。對于黑客主機(jī)的客戶端,是沒招的;但我們可以限制一臺(tái)主機(jī)對應(yīng)一個(gè)服務(wù)端口,只給它50個(gè)連接。虛就虛著吧,又能飛天?我服務(wù)端可以有1千多萬個(gè)連接,怕誰?黑客搞搞震,不就浪費(fèi)自己的電費(fèi)、資源。黑客們,千萬不要讓你們的肉雞進(jìn)入監(jiān)視名單,那將是你們的噩夢。二、網(wǎng)絡(luò)v節(jié)點(diǎn)什么是內(nèi)存v節(jié)點(diǎn)?內(nèi)存v節(jié)點(diǎn)是大小為4E=128B的一個(gè)內(nèi)存結(jié)構(gòu)變量,APO中最多可以有16M個(gè)v節(jié)點(diǎn)。V節(jié)點(diǎn)與在內(nèi)存中打開的文件是——對應(yīng)的,網(wǎng)絡(luò)sockfd文件號(hào)實(shí)際上也就是v節(jié)點(diǎn)號(hào)。我們將網(wǎng)絡(luò)socket看作是一個(gè)文件,所以、與網(wǎng)絡(luò)socket文件必定對應(yīng)有一個(gè)網(wǎng)絡(luò)v節(jié)點(diǎn)。一定要牢記v節(jié)點(diǎn)就是代表在內(nèi)存中打開的文件,每個(gè)v節(jié)點(diǎn)號(hào)、對應(yīng)一個(gè)文件。v節(jié)點(diǎn)的內(nèi)容就是對一個(gè)文件的屬性描述,對于網(wǎng)絡(luò)socket文件就是對一個(gè)連接的描述。1、v節(jié)點(diǎn)號(hào)與普通文件號(hào)fd的區(qū)別

我們必須搞清這2個(gè)概念的區(qū)別,對于網(wǎng)絡(luò)socket文件、與進(jìn)程或線程是唯一對應(yīng)的;所以,網(wǎng)絡(luò)socket文件號(hào)sockfd與v節(jié)點(diǎn)號(hào)是一致的。但是,對于在內(nèi)存中打開的文件、對應(yīng)一個(gè)唯一的v節(jié)點(diǎn)號(hào);但可能對應(yīng)著許多進(jìn)程或線程。所以,為了區(qū)分不同進(jìn)程或線程在內(nèi)存中打開同一個(gè)文件;我們使用了文件描述符、即文件號(hào)fd,和文件打開表項(xiàng)。文件號(hào)fd與進(jìn)程的文件打開表項(xiàng)是一一對應(yīng)的,或許2個(gè)進(jìn)程有相同的文件號(hào),但不一定對應(yīng)相同的v節(jié)點(diǎn)、這取決于它們的文件打開表項(xiàng)。所以,我們只能說文件號(hào)fd代表的是進(jìn)程的文件打開表項(xiàng),在進(jìn)程的文件打開表項(xiàng)有對v節(jié)點(diǎn)的引用,用戶定義的流容器的引用等等。對于普通文件的v節(jié)點(diǎn)就是對應(yīng)文件的i節(jié)點(diǎn)屬性和其所屬父目錄中的目錄項(xiàng)屬性;請參看前面的章節(jié)。注意:網(wǎng)絡(luò)socket文件是沒有目錄項(xiàng)和i節(jié)點(diǎn)的,只有v節(jié)點(diǎn);網(wǎng)絡(luò)v節(jié)點(diǎn)描述的是一個(gè)連接,是本章需要論述的。2、描述一個(gè)連接的網(wǎng)絡(luò)v節(jié)點(diǎn)socket文件是在內(nèi)存建立的、和其它類型的文件不一樣,無須i節(jié)點(diǎn)、目錄項(xiàng),也不需要文件打開表項(xiàng);只有不一樣的v節(jié)點(diǎn),描述了一個(gè)連接。網(wǎng)絡(luò)v節(jié)點(diǎn)就是描述網(wǎng)絡(luò)通信雙方的標(biāo)識(shí)和協(xié)議,包含通信協(xié)議頭及建立、或釋放連接的一些參數(shù)。APO中,帶連接的UDP協(xié)議和TCP的合一;所以,除了無連接的ICMP外,APO就只有一個(gè)TCP協(xié)議了。APO的TCP協(xié)議也想將應(yīng)用層協(xié)議(HTTP、FTP、TFTP、TELNET、PRC等)的一部分柔和進(jìn)來;前面的章節(jié)關(guān)于協(xié)議部分需要修改。APO的TCP協(xié)議與現(xiàn)有的不一樣,做了簡化及性能的加強(qiáng);要快速多了,跟無連接的DUP差不了多少。取消了麻煩、低效的窗口、序號(hào)、確認(rèn)號(hào);使用了獨(dú)特、高效、高速的重傳機(jī)制。APO的最小數(shù)據(jù)包是64B+4B(CRC)+8B(同步頭)=76B;最大普通數(shù)據(jù)包是:23*64B+12B=1484B,最大ICMP的數(shù)據(jù)包是:47*32B+12B=1516B。路由交換機(jī)的MTU,如果小于1516B,

不分段、不丟包,只是截?cái)唷U4Esocket_vnode{//socket文件的網(wǎng)絡(luò)v節(jié)點(diǎn)。BU1EIPAPO{//APO的IP頭。BU48MDA;//以太網(wǎng)目標(biāo)地址BU48MSA;//以太網(wǎng)源地址BU16TYPE;//類型高5位和低11位的長度。BU8TTL;//跳數(shù)限制。BU8TOS;//8位傳輸優(yōu)先級、流量類型。BU64SLADD;//源鏈路地址。SLADD+MSA=源IP地址BU64DLADD;//目標(biāo)鏈路地址。DLADD+MDA=目標(biāo)IP地址}union{//APO的TCP協(xié)議頭、1E;支持4GB的文件流傳輸。BU32length;//文件流總字節(jié)長度,不含頭部64字節(jié)(2E)。BU32sheetoff;//低26位片偏移、分段單位1片=64字節(jié)。//sheetoff.31-26request;上層協(xié)議的請求方法標(biāo)識(shí)。Read、write、GET、//POST、PUT、DELETE、TRACE、CONNECT、PATCH、ABOR、ACCT等等;或自定義。BU8trflag;//傳輸控制標(biāo)志。//trflag.7MF;更多分段

溫馨提示

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

評論

0/150

提交評論