TCP/IP協(xié)議
為了把全世界的所有不同類型的計算機(jī)都連接起來,就必須規(guī)定一套全球通用的協(xié)議,為了實現(xiàn)互聯(lián)網(wǎng)這個目標(biāo),誕生了互聯(lián)網(wǎng)協(xié)議簇(Internet Protocol Suite)就是通用協(xié)議標(biāo)準(zhǔn)。這里面有上百種協(xié)議,不過最重要的還是TCP/IP協(xié)議。
TCP協(xié)議的特點(diǎn)
TCP通信模型中,在通信開始之前,一定要先建立相關(guān)的鏈接,才能發(fā)送數(shù)據(jù),類似于生活中,"打電話"。通信連接必須是雙向的,有明顯的客戶端與服務(wù)器,只能在完全接收到服務(wù)器給的響應(yīng)后才能發(fā)起下一次請求,并且超時之后還有重發(fā)機(jī)制,在通信過程中不會存在丟包現(xiàn)象,是一種安全的可靠的傳輸協(xié)議。
TCP連接的三次握手四次揮手
TCP協(xié)議,客戶端與服務(wù)器建立連接:三次握手
簡單來說就是:
第一次握手:客戶端向指定的地址發(fā)送連接請求,開啟了一個socket,并且
????攜帶了請求的信息;
第二次握手:服務(wù)器收到請求,被動開啟一個socket準(zhǔn)備連接客戶端,
????同時發(fā)送數(shù)據(jù)告訴客戶端“我已經(jīng)準(zhǔn)備好了,讓我們交合吧!”;
第三次握手:客戶端收到服務(wù)器的信息,返回給服務(wù)器,正式建立連接。
TCP協(xié)議,客戶端與服務(wù)器斷開連接:四次揮手
第一次揮手:客戶端發(fā)送報文,表示沒有請求信息了,準(zhǔn)備關(guān)閉連接;
第二次揮手:服務(wù)器收到信息,首先將還沒有傳給客戶端的信息全部傳回去;
第三次揮手:服務(wù)器表示收到了關(guān)閉連接的信息,告訴客戶端我已關(guān)閉連接;
第四次揮手:客戶端收到信息,關(guān)閉連接。
這里的連接斷開過程,充分體現(xiàn)了TCP協(xié)議的可靠性,和雙向性。
網(wǎng)絡(luò)中的不同計算機(jī)進(jìn)程間通信是通過socket實現(xiàn)的,下面會講到。
UDP協(xié)議
UDP協(xié)議的特點(diǎn)
UDP --- 用戶數(shù)據(jù)報協(xié)議,是一個無連接的簡單的面向數(shù)據(jù)報的運(yùn)輸層協(xié)議。UDP不提供可靠性,它只是把應(yīng)用程序傳給IP層的數(shù)據(jù)報發(fā)送出去,但是并不能保證它們能到達(dá)目的地。由于UDP在傳輸數(shù)據(jù)報前不用在客戶和服務(wù)器之間建立一個連接,且沒有超時重發(fā)等機(jī)制,故而傳輸速度很快。
UDP是一種面向無連接的協(xié)議,每個數(shù)據(jù)報都是一個獨(dú)立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡(luò)上以任何可能的路徑傳往目的地,因此能否到達(dá)目的地,到達(dá)目的地的時間以及內(nèi)容的正確性都是不能被保證的,所以可以用來數(shù)據(jù)廣播。
UDP傳輸數(shù)據(jù)時有大小限制,每個被傳輸?shù)臄?shù)據(jù)報必須限定在64KB之內(nèi)。 UDP是一個不可靠的協(xié)議,發(fā)送方所發(fā)送的數(shù)據(jù)報并不一定以相同的次序到達(dá)接收方。
socket簡介
在之前的多進(jìn)程里面介紹過,進(jìn)程間的通信可以通過隊列Queue,管道等進(jìn)行數(shù)據(jù)的交互通信,或者通過Manager進(jìn)行數(shù)據(jù)共享,但是網(wǎng)絡(luò)中不同計算機(jī)之間不同進(jìn)程的交互就不能做到了。
其實TCP/IP協(xié)議族已經(jīng)幫我們解決了這個問題,網(wǎng)絡(luò)層的“ip地址”可以唯一標(biāo)識網(wǎng)絡(luò)中的主機(jī),而傳輸層的“協(xié)議+端口”可以唯一標(biāo)識主機(jī)中的應(yīng)用程序(進(jìn)程)。
這樣利用ip地址,協(xié)議,端口就可以標(biāo)識網(wǎng)絡(luò)的進(jìn)程了,網(wǎng)絡(luò)中的進(jìn)程通信就可以利用這個標(biāo)志與其它進(jìn)程進(jìn)行交互。
socket(簡稱 套接字) 是進(jìn)程間通信的一種方式,它與其他進(jìn)程間通信的一個主要不同是:它能實現(xiàn)不同主機(jī)間的進(jìn)程間通信,我們網(wǎng)絡(luò)上各種各樣的服務(wù)大多都是基于 Socket 來完成通信的,socket就像計算機(jī)上的插座一樣,當(dāng)有其他計算機(jī)的進(jìn)程要連接時,對應(yīng)端口的socket就會啟動,實現(xiàn)與其他計算機(jī)進(jìn)程的連接。
TCP的長連接與短連接
TCP長連接
建立連接——數(shù)據(jù)傳輸...(保持連接)...數(shù)據(jù)傳輸——關(guān)閉連接
1、client 向 server 發(fā)起連接
2、server 接到請求,雙方建立連接
3、client 向 server 發(fā)送消息
4、server 回應(yīng) client
5、一次讀寫完成,連接不關(guān)閉
6、后續(xù)讀寫操作...
7、長時間操作之后client發(fā)起關(guān)閉請求
TCP短連接
建立連接——數(shù)據(jù)傳輸——關(guān)閉連接...建立連接——數(shù)據(jù)傳輸——關(guān)閉連接
1、client 向 server 發(fā)起連接請求
2、server 接到請求,雙方建立連接
3、client 向 server 發(fā)送消息
4、server 回應(yīng) client
5、一次讀寫完成,此時雙方任何一個都可以發(fā)起 close 操作
注意:在第 步驟5中,一般都是 client 先發(fā)起 close 操作。當(dāng)然也不排除有特殊的情況。
從上面的描述看,短連接一般只會在 client/server 間傳遞一次讀寫操作!
HTTP協(xié)議就是一種典型的TCP短連接協(xié)議。
長短連接的優(yōu)缺點(diǎn):
◆長連接可以省去較多的TCP建立和關(guān)閉的操作,減少浪費(fèi),節(jié)約時間。
◆對于頻繁請求資源的客戶來說,較適用長連接。
◆隨著客戶端連接越來越多,server早晚有扛不住的時候,這時候server端
? ?需要采取一些策略:
? ?如關(guān)閉一些長時間沒有讀寫事件發(fā)生的連接,這樣可以 避免一些惡意連接導(dǎo)致
? ?server端服務(wù)受損;
? ?如果條件再允許就可以以客戶端機(jī)器為顆粒度,限制每個客戶端的最大長連接
? ?數(shù),這樣可以完全避免某個客戶端連累后端服務(wù)。
◆短連接對于服務(wù)器來說管理較為簡單,存在的連接都是有用的連接,不需要額外的控制手段。
◆但如果客戶請求頻繁,將在TCP的建立和關(guān)閉操作上浪費(fèi)時間和帶寬。
TCP長短連接的適用實例
長連接:多用于操作頻繁,點(diǎn)對點(diǎn)的通訊,而且連接數(shù)不能太多情況。每個TCP連接都需要三次握手,這需要時間,如果每個操作都是先連接,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開,再次處理時直接發(fā)送數(shù)據(jù)包就OK了,不用建立TCP連接。例如:數(shù)據(jù)庫的連接用長連接,如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創(chuàng)建也是對資源的浪費(fèi)。
短連接:像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以并發(fā)量大,但每個用戶無需頻繁操作情況下需用短連好。所以web中的HTTP才使用短連接。
常見網(wǎng)絡(luò)攻擊與防范
SYN洪水攻擊,大量發(fā)起請求但是卻不執(zhí)行操作,讓服務(wù)器短時間內(nèi)建立很多的連接,導(dǎo)致服務(wù)器在正常用戶訪問時,拒絕服務(wù),應(yīng)對措施:合理設(shè)置連接超時時間
Web欺騙,位于客戶端和服務(wù)器之間,接收客戶端的正確請求,轉(zhuǎn)發(fā)給服務(wù)器,但是缺展示假的頁面給客戶端,自己獲取服務(wù)器的真實信息,危害很大,應(yīng)對措施:對信息進(jìn)行加密,攻擊者無法破解密文,進(jìn)行后續(xù)操作。
CSRF跨域請求偽造:客戶端誤進(jìn)入一個有害的網(wǎng)站,其中包含有對另一個域名的服務(wù)器敏感信息的操作請求,在解析網(wǎng)頁的時候,會執(zhí)行這個敏感請求。應(yīng)對措施:服務(wù)器在建立連接時發(fā)送一段密文,之后繼續(xù)訪問該域名下的其他操作,必須帶著域名提交,否則返回403錯誤,django常用{% csrf_token %}。
XSS腳本植入攻擊:惡意攻擊者往Web頁面里插入惡意Script代碼,當(dāng)用戶瀏覽該頁之時,嵌入其中Web里面的Script代碼會被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。防范:輸入檢查和輸出檢查,django中常用autoescape標(biāo)簽的參數(shù)是on或者off,如果{% autoescape off %}標(biāo)簽中有需要轉(zhuǎn)義的內(nèi)容,則可以在該標(biāo)簽中嵌套使用{% autoescape on %}
單進(jìn)程服務(wù)器異步非阻塞IO操作的原理
select
1. select 原理
在多路復(fù)用的模型中,比較常用的有select模型和epoll模型。這兩個都是系統(tǒng)接口,由操作系統(tǒng)提供。當(dāng)然,Python的select模塊進(jìn)行了更高級的封裝。
網(wǎng)絡(luò)通信被Unix系統(tǒng)抽象為文件的讀寫,通常是一個設(shè)備,由設(shè)備驅(qū)動程序提供,驅(qū)動可以知道自身的數(shù)據(jù)是否可用。支持阻塞操作的設(shè)備驅(qū)動通常會實現(xiàn)一組自身的等待隊列,如讀/寫等待隊列用于支持上層(用戶層)所需的block或non-block操作。設(shè)備的文件的資源如果可用(可讀或者可寫)則會通知進(jìn)程,反之則會讓進(jìn)程睡眠,等到數(shù)據(jù)到來可用的時候,再喚醒進(jìn)程。
這些設(shè)備的文件描述符被放在一個數(shù)組中,然后select調(diào)用的時候遍歷這個數(shù)組,如果對于的文件描述符可讀則會返回改文件描述符。當(dāng)遍歷結(jié)束之后,如果仍然沒有一個可用設(shè)備文件描述符,select讓用戶進(jìn)程則會睡眠,直到等待資源可用的時候在喚醒,遍歷之前那個監(jiān)視的數(shù)組。每次遍歷都是依次進(jìn)行判斷的。
2、select缺陷
select的一個缺點(diǎn)在于單個進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,在Linux上一般為1024,可以通過修改宏定義甚至重新編譯內(nèi)核的方式提升這一限制,但是這樣也會造成效率的降低。
一般來說這個數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大,具體數(shù)目可以cat /proc/sys/fs/file-max察看。32位機(jī)默認(rèn)是1024個。64位機(jī)默認(rèn)是2048.
對socket進(jìn)行掃描時是依次掃描的,即采用輪詢的方法,效率較低。
當(dāng)套接字比較多的時候,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調(diào)度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費(fèi)很多CPU時間。
epoll
1. epoll的優(yōu)點(diǎn):
沒有最大并發(fā)連接的限制,能打開的FD(指的是文件描述符,通俗的理解就是套接字對應(yīng)的數(shù)字編號)的上限遠(yuǎn)大于1024
效率提升,不是輪詢的方式,不會隨著FD數(shù)目的增加效率下降。只有活躍可用的FD才會調(diào)用callback函數(shù);即epoll最大的優(yōu)點(diǎn)就在于它只管你“活躍”的連接,而跟連接總數(shù)無關(guān),因此在實際的網(wǎng)絡(luò)環(huán)境中,epoll的效率就會遠(yuǎn)遠(yuǎn)高于select和poll。
2.基于epoll的web服務(wù)器
Tornado框架自帶的web服務(wù)器,就是在linux系統(tǒng)中使用epoll單進(jìn)程異步非阻塞AIO操作,實現(xiàn)高并發(fā)操作,當(dāng)Tornado中使用多進(jìn)程操作時,它的性能將會發(fā)揮到最大值,在處理高并發(fā)的用戶量比較大的web項目時,發(fā)揮強(qiáng)大的作用。