TCP與UDP通信

一、TCP/IP協(xié)議

TCP/IP網(wǎng)絡(luò)協(xié)議分為:應(yīng)用層(Telnet、FTP、e-mail...)、傳輸層(TCP、UDP)、網(wǎng)絡(luò)層(IP、ICMP...)、鏈路層(設(shè)備驅(qū)動(dòng)程序及接口卡) 四層

傳輸層及其以下的機(jī)制由內(nèi)核提供,應(yīng)用層由用戶進(jìn)程提供,應(yīng)用程序?qū)νㄓ崝?shù)據(jù)的含義進(jìn)行解釋,而傳輸層及其以下處理通訊的細(xì)節(jié),將數(shù)據(jù)從一臺(tái)計(jì)算機(jī)通過(guò)一定的路徑發(fā)送到另一臺(tái)計(jì)算機(jī)。應(yīng)用層數(shù)據(jù)通過(guò)協(xié)議棧發(fā)到網(wǎng)絡(luò)上時(shí),每層協(xié)議都要加上一個(gè)數(shù)據(jù)首部(header),稱為封裝(Encapsulation)

Mou icon

不同的協(xié)議層對(duì)數(shù)據(jù)包有不同的稱謂,在傳輸層叫做段(segment),在網(wǎng)絡(luò)層叫做數(shù)據(jù)報(bào) (datagram),在鏈路層叫做幀(frame)。數(shù)據(jù)封裝成幀后發(fā)到傳輸介質(zhì)上,到達(dá)目的主機(jī)后每層協(xié)議再剝掉相應(yīng)的首部,最后將應(yīng)用層數(shù)據(jù)交給應(yīng)用程序處理

Markdown

其實(shí)在鏈路層之下還有物理層,指的是電信號(hào)的傳遞方式,比如現(xiàn)在以太網(wǎng)通用的網(wǎng)線(雙絞線)、早期以太網(wǎng)采用的的同軸電纜(現(xiàn)在主要用于有線電視)、光纖等都屬于物理層的概念。物理層的能力決定了最大傳輸速率、傳輸距離、抗干擾性等。集線器(Hub)是工作在物理層的網(wǎng)絡(luò)設(shè)備,用于雙絞線的連接和信號(hào)中繼(將已衰減的信號(hào)再次放大使之傳得更遠(yuǎn))。

鏈路層有以太網(wǎng)、令牌環(huán)網(wǎng)等標(biāo)準(zhǔn),鏈路層負(fù)責(zé)網(wǎng)卡設(shè)備的驅(qū)動(dòng)、幀同步(就是說(shuō)從網(wǎng)線上檢測(cè)到什么信號(hào)算作新幀的開(kāi)始)、沖突檢測(cè)(如果檢測(cè)到?jīng)_突就自動(dòng)重發(fā))、數(shù)據(jù)差錯(cuò)校驗(yàn)等工作。交換機(jī)是工作在鏈路層的網(wǎng)絡(luò)設(shè)備,可以在不同的鏈路層網(wǎng)絡(luò)之間轉(zhuǎn)發(fā)數(shù)據(jù)幀(比如十兆以太網(wǎng)和百兆以太網(wǎng)之間、以太網(wǎng)和令牌環(huán)網(wǎng)之間),由于不同鏈路層的幀格式不同,交換機(jī)要將進(jìn)來(lái)的數(shù)據(jù)包拆掉鏈路層首部重新封裝之后再轉(zhuǎn)發(fā)。

網(wǎng)絡(luò)層的IP協(xié)議是構(gòu)成Internet的基礎(chǔ)。Internet上的主機(jī)通過(guò)IP地址來(lái)標(biāo)識(shí),Internet上有大量路由器負(fù)責(zé)根據(jù)IP地址選擇合適的路徑轉(zhuǎn)發(fā)數(shù)據(jù)包,數(shù)據(jù)包從Internet上的源主機(jī)到目的主機(jī)往往要經(jīng)過(guò)十多個(gè)路由器。路由器是工作在第三層的網(wǎng)絡(luò)設(shè)備,同時(shí)兼有交換機(jī)的功能,可以在不同的鏈路層接口之間轉(zhuǎn)發(fā)數(shù)據(jù)包,因此路由器需要將進(jìn)來(lái)的數(shù)據(jù)包拆掉網(wǎng)絡(luò)層和鏈路層兩層首部并重新封裝。IP協(xié)議不保證傳輸?shù)目煽啃裕瑪?shù)據(jù)包在傳輸過(guò)程中可能丟失,可靠性可以在上層協(xié)議或應(yīng)用程序中提供支持。

網(wǎng)絡(luò)層負(fù)責(zé)點(diǎn)到點(diǎn)(point-to-point)的傳輸(這里的“點(diǎn)”指主機(jī)或路由器),而傳輸層負(fù)責(zé)端到端(end-to-end)的傳輸(這里的“端”指源主機(jī)和目的主機(jī))。傳輸層可選擇TCP或UDP協(xié) 議。TCP是一種面向連接的、可靠的協(xié)議,有點(diǎn)像打電話,雙方拿起電話互通身份之后就建立了連接,然后說(shuō)話就行了,這邊說(shuō)的話那邊保證聽(tīng)得到,并且是按說(shuō)話的順序聽(tīng)到的,說(shuō)完話掛機(jī)斷開(kāi)連接。也就是說(shuō)TCP傳輸?shù)碾p方需要首先建立連接,之后由TCP協(xié)議保證數(shù)據(jù)收發(fā)的可靠性,丟失的數(shù)據(jù)包自動(dòng)重發(fā),上層應(yīng)用程序收到的總是可靠的數(shù)據(jù)流,通訊之后關(guān)閉連接。UDP協(xié)議不面向連接,也不保證可靠性,有點(diǎn)像寄信,寫(xiě)好信放到郵筒里,既不能保證信件在郵遞過(guò)程中不會(huì)丟失,也不能保證信件是按順序寄到目的地的。使用UDP協(xié)議的應(yīng)用程序需要自己完成丟包重發(fā)、消息排序等工作。

以太網(wǎng)驅(qū)動(dòng)程序首先根據(jù)以太網(wǎng)首部中的“上層協(xié)議”字段確定該數(shù)據(jù)幀的有效載荷(payload,指除去協(xié)議首部之外實(shí)際傳輸?shù)臄?shù)據(jù))是IP、ARP還是RARP協(xié)議的數(shù)據(jù)報(bào),然后交給相應(yīng)的協(xié)議處理。假如是IP數(shù)據(jù)報(bào),IP協(xié)議再根據(jù)IP首部中的“上層協(xié)議”字段確定該數(shù)據(jù)報(bào)的有效載荷是TCP、UDP、ICMP還是IGMP,然后交給相應(yīng)的協(xié)議處理。假如是TCP段 或UDP段,TCP或UDP協(xié)議再根據(jù)TCP首部或UDP首部的“端口號(hào)”字段確定應(yīng)該將應(yīng)用層數(shù)據(jù)交給哪個(gè)用戶進(jìn)程。IP地址是標(biāo)識(shí)網(wǎng)絡(luò)中不同主機(jī)的地址,而端口號(hào)就是同一臺(tái)主機(jī)上標(biāo)識(shí)不同進(jìn)程的地址,IP地址和端口號(hào)合起來(lái)標(biāo)識(shí)網(wǎng)絡(luò)中唯一的進(jìn)程。

二、TCP的三次握手與四次揮手

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送3個(gè)包以確認(rèn)連接的建立。在socket編程中,這一過(guò)程由客戶端執(zhí)行connect來(lái)觸發(fā)

(1)第一次握手:Client將標(biāo)志位SYN置為1,隨機(jī)產(chǎn)生一個(gè)值seq=J,并將該數(shù)據(jù)包發(fā)送給Server,Client進(jìn)入SYN_SENT狀態(tài),等待Server確認(rèn)。

(2)第二次握手:Server收到數(shù)據(jù)包后由標(biāo)志位SYN=1知道Client請(qǐng)求建立連接,Server將標(biāo)志位SYN和ACK都置為1,ack=J+1,隨機(jī)產(chǎn)生一個(gè)值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請(qǐng)求,Server進(jìn)入SYN_RCVD狀態(tài)。

(3)第三次握手:Client收到確認(rèn)后,檢查ack是否為J+1,ACK是否為1,如果正確則將標(biāo)志位ACK置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進(jìn)入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開(kāi)始傳輸數(shù)據(jù)了。

SYN攻擊:
在三次握手過(guò)程中,Server發(fā)送SYN-ACK之后,收到Client的ACK之前的TCP連接稱為半連接(half-open connect),此時(shí)Server處于SYN_RCVD狀態(tài),當(dāng)收到ACK后,Server轉(zhuǎn)入ESTABLISHED狀態(tài)。SYN攻擊就是Client在短時(shí)間內(nèi)偽造大量不存在的IP地址,并向Server不斷地發(fā)送SYN包,Server回復(fù)確認(rèn)包,并等待Client的確認(rèn),由于源地址是不存在的,因此,Server需要不斷重發(fā)直至超時(shí),這些偽造的SYN包將產(chǎn)時(shí)間占用未連接隊(duì)列,導(dǎo)致正常的SYN請(qǐng)求因?yàn)殛?duì)列滿而被丟棄,從而引起網(wǎng)絡(luò)堵塞甚至系統(tǒng)癱瘓。SYN攻擊時(shí)一種典型的DDOS攻擊,檢測(cè)SYN攻擊的方式非常簡(jiǎn)單,即當(dāng)Server上有大量半連接狀態(tài)且源IP地址是隨機(jī)的,則可以斷定遭到SYN攻擊了

所謂四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開(kāi)一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送4個(gè)包以確認(rèn)連接的斷開(kāi)。在socket編程中,這一過(guò)程由客戶端或服務(wù)端任一方執(zhí)行close來(lái)觸發(fā)

由于TCP連接時(shí)全雙工的,因此,每個(gè)方向都必須要單獨(dú)進(jìn)行關(guān)閉,這一原則是當(dāng)一方完成數(shù)據(jù)發(fā)送任務(wù)后,發(fā)送一個(gè)FIN來(lái)終止這一方向的連接,收到一個(gè)FIN只是意味著這一方向上沒(méi)有數(shù)據(jù)流動(dòng)了,即不會(huì)再收到數(shù)據(jù)了,但是在這個(gè)TCP連接上仍然能夠發(fā)送數(shù)據(jù),直到這一方向也發(fā)送了FIN。首先進(jìn)行關(guān)閉的一方將執(zhí)行主動(dòng)關(guān)閉,而另一方則執(zhí)行被動(dòng)關(guān)閉

(1)第一次揮手:Client發(fā)送一個(gè)FIN,用來(lái)關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)。

(2)第二次揮手:Server收到FIN后,發(fā)送一個(gè)ACK給Client,確認(rèn)序號(hào)為收到序號(hào)+1(與SYN相同,一個(gè)FIN占用一個(gè)序號(hào)),Server進(jìn)入CLOSE_WAIT狀態(tài)。

(3)第三次揮手:Server發(fā)送一個(gè)FIN,用來(lái)關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK狀態(tài)。

(4)第四次揮手:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個(gè)ACK給Server,確認(rèn)序號(hào)為收到序號(hào)+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。

三、TCP的客戶端和服務(wù)端實(shí)現(xiàn)解析

(1)connect()函數(shù)

對(duì)于客戶端的 connect() 函數(shù),該函數(shù)的功能為客戶端主動(dòng)連接服務(wù)器,建立連接是通過(guò)三次握手,而這個(gè)連接的過(guò)程是由內(nèi)核完成,不是這個(gè)函數(shù)完成的,這個(gè)函數(shù)的作用僅僅是通知 Linux 內(nèi)核,讓 Linux 內(nèi)核自動(dòng)完成 TCP 三次握手連接,最后把連接的結(jié)果返回給這個(gè)函數(shù)的返回值(成功連接為0, 失敗為-1)。

通常的情況,客戶端的 connect() 函數(shù)默認(rèn)會(huì)一直阻塞,直到三次握手成功或超時(shí)失敗才返回(正常的情況,這個(gè)過(guò)程很快完成)。

(2)listen()函數(shù)
int listen(int sockfd, int backlog); 

對(duì)于服務(wù)器,它是被動(dòng)連接的。listen() 函數(shù)的主要作用就是將套接字( sockfd )變成被動(dòng)的連接監(jiān)聽(tīng)套接字(被動(dòng)等待客戶端的連接),至于參數(shù) backlog 的作用是設(shè)置內(nèi)核中連接隊(duì)列的長(zhǎng)度

這里需要注意的是,listen()函數(shù)不會(huì)阻塞,它主要做的事情為,將該套接字和套接字對(duì)應(yīng)的連接隊(duì)列長(zhǎng)度告訴 Linux 內(nèi)核,然后,listen()函數(shù)就結(jié)束。

這樣的話,當(dāng)有一個(gè)客戶端主動(dòng)連接(connect()),Linux 內(nèi)核就自動(dòng)完成TCP 3次握手,將建立好的鏈接自動(dòng)存儲(chǔ)到隊(duì)列中,如此重復(fù)。

所以,只要 TCP 服務(wù)器調(diào)用了 listen(),客戶端就可以通過(guò) connect() 和服務(wù)器建立連接,而這個(gè)連接的過(guò)程是由內(nèi)核完成。

為了更好的理解 backlog 參數(shù),我們必須認(rèn)識(shí)到內(nèi)核為任何一個(gè)給定的監(jiān)聽(tīng)套接口維護(hù)兩個(gè)隊(duì)列:

1、未完成連接隊(duì)列(incomplete connection queue),每個(gè)這樣的 SYN 分節(jié)對(duì)應(yīng)其中一項(xiàng):已由某個(gè)客戶發(fā)出并到達(dá)服務(wù)器,而服務(wù)器正在等待完成相應(yīng)的 TCP三次握手過(guò)程。這些套接口處于 SYN_RCVD 狀態(tài)。

2、已完成連接隊(duì)列(completed connection queue),每個(gè)已完成 TCP 三次握手過(guò)程的客戶對(duì)應(yīng)其中一項(xiàng)。這些套接口處于 ESTABLISHED 狀態(tài)。

當(dāng)來(lái)自客戶的 SYN 到達(dá)時(shí),TCP 在未完成連接隊(duì)列中創(chuàng)建一個(gè)新項(xiàng),然后響應(yīng)以三次握手的第二個(gè)分節(jié):服務(wù)器的 SYN 響應(yīng),其中稍帶對(duì)客戶 SYN 的 ACK(即SYN+ACK),這一項(xiàng)一直保留在未完成連接隊(duì)列中,直到三次握手的第三個(gè)分節(jié)(客戶對(duì)服務(wù)器 SYN 的 ACK )到達(dá)或者該項(xiàng)超時(shí)為止(曾經(jīng)源自Berkeley的實(shí)現(xiàn)為這些未完成連接的項(xiàng)設(shè)置的超時(shí)值為75秒)。

如果三次握手正常完成,該項(xiàng)就從未完成連接隊(duì)列移到已完成連接隊(duì)列的隊(duì)尾。

backlog 參數(shù)歷史上被定義為上面兩個(gè)隊(duì)列的大小之和,大多數(shù)實(shí)現(xiàn)默認(rèn)值為 5,當(dāng)服務(wù)器把這個(gè)完成連接隊(duì)列的某個(gè)連接取走后,這個(gè)隊(duì)列的位置又空出一個(gè),這樣來(lái)回實(shí)現(xiàn)動(dòng)態(tài)平衡,但在高并發(fā) web 服務(wù)器中此值顯然不夠。

(3)accept()函數(shù)

accept()函數(shù)功能是,從處于 established 狀態(tài)的連接隊(duì)列頭部取出一個(gè)已經(jīng)完成的連接,如果這個(gè)隊(duì)列沒(méi)有已經(jīng)完成的連接,accept()函數(shù)就會(huì)阻塞,直到取出隊(duì)列中已完成的用戶連接為止

Markdown

四、UDP的實(shí)現(xiàn)

與 TCP 不同, UDP 并不提供對(duì) IP 協(xié)議的可靠機(jī)制、流控制以及錯(cuò)誤恢復(fù) 功能等。由于 UDP 比較簡(jiǎn)單, UDP 頭包含很少的字節(jié),比TCP負(fù)載消耗少。 UDP適用于不需要TCP可靠機(jī)制的情形,比如,當(dāng)高層協(xié)議或應(yīng)用程序提供錯(cuò) 誤和流控制功能的時(shí)候。

UDP套接口是無(wú)連接的、不可靠的數(shù)據(jù)報(bào)協(xié)議;既然他不可靠為什么還要用呢?其一:當(dāng)應(yīng)用程序使用廣播或多播時(shí)只能使用UDP協(xié)議;其二:由于他是無(wú)連接的,所以速度快。因?yàn)閁DP套接口是無(wú)連接的,如果一方的數(shù)據(jù)報(bào)丟失,那另一方將無(wú)限等待,解決辦法是設(shè)置一個(gè)超時(shí)。

建立UDP套接口時(shí)socket函數(shù)的第二個(gè)參數(shù)應(yīng)該是SOCK_DGRAM,說(shuō)明是建立一個(gè)UDP套接口;

由于UDP是無(wú)連接的,所以服務(wù)器端并不需要listen或accept函數(shù)。

使用UDP套接字編程可以實(shí)現(xiàn)基于TCP/IP協(xié)議的面向無(wú)連接的通信

Markdown

參考文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、TCP狀態(tài)linux查看tcp的狀態(tài)命令:1)、netstat -nat 查看TCP各個(gè)狀態(tài)的數(shù)量2)、lso...
    北辰青閱讀 9,723評(píng)論 0 11
  • 參考:http://www.2cto.com/net/201611/569006.html TCP HTTP UD...
    F麥子閱讀 3,069評(píng)論 0 14
  • 18.1 引言 TCP是一個(gè)面向連接的協(xié)議。無(wú)論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接。本章將...
    張芳濤閱讀 3,529評(píng)論 0 13
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,195評(píng)論 0 8
  • 1.這篇文章不是本人原創(chuàng)的,只是個(gè)人為了對(duì)這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,375評(píng)論 6 174

友情鏈接更多精彩內(nèi)容