前言
原文html
10. 網絡編程
- 互聯網通訊所要遵照的衆多協議,被統稱爲TCP/IP。
10.1 簡要網絡知識
- TCP/IP是一個龐大的協議族,它是衆多網絡協議的集合,包括:ARP、IP、ICMP、UDP、TCP、DNS、DHCP、HTTP、FTP、MQTT等等
- 分層
graph LR A[應用層] --> a[DNS HTTP FTP SMTP MQTT郵件協議] B[傳輸層] --> b[主要是TCP UDP] C[網絡層] --> c[主要爲IP ICM ARP協議] D[鏈路層] --> d[MAC層] E[物理層] --> e[主要定義物理傳輸介質]
10.2 IP協議
- IP協議(Internet Protocol),又稱之爲網際協議,IP協議處於IP層工做,它是整個TCP/IP協議棧的核心協議
10.2.1 IP地址編址
類別 |
第一字節(二進制) |
第一字節取值範圍 |
網絡號個數 |
主機號個數 |
適用範圍 |
A類 |
0XXX XXXX |
0-127 |
125 |
16777214 |
大型網絡 |
B類 |
10XX XXXX |
128-191 |
16368 |
65534 |
中型網絡 |
C類 |
110X XXXX |
192-223 |
209715 |
254 |
小型網絡 |
D類 |
1110 XXXX |
224-239 |
- |
- |
多播 |
E類 |
1111 XXXX |
240-255 |
- |
- |
保留 |
10.2.2 特殊IP地址
10.2.1 首限廣播地址
- 受限廣播地址用於定義整個互聯網,若是設備想使IP數據報被整個網絡所接收,就發送這個目的地址全爲1的廣播包,但這樣會給整個互聯網帶來災難性的負擔,因此在任何狀況下,路由器都會禁止轉發目的地址爲255.255.255.255的廣播數據包,所以這樣的數據包僅會出如今本地網絡中(局域網),255.255.255.255這個地址指本網段內的全部主機, 至關於「房子裏面的人都聽着」通知全部主機。
- 其實就是對整個IP生效,即網絡號+主機號都全爲1,對整個互聯網生效
10.2.2 直接廣播地址
- 直接廣播地址僅是主機號爲1,廣播地址表明本網絡內的全部主機。
- 其實就是對整個IP生效,即主機號都全爲1,對同一網絡號內的全部主機生效
10.2.3 多播地址
- 多播地址用在一對多的通訊中,屬於分類編址中的D類地址, D類地址只能用做目的地址,而不能做爲主機中的源地址。
10.2.4 迴環地址
- 127網段的全部地址都稱爲環回地址,主要用來測試網絡協議是否工做正常的做用。好比在電腦中使用ping 命令去ping 127.1.1.1就能夠測試本地TCP/IP協議是否正常。用通俗的話表示,就是「我本身」,不能以127網段中的IP地址做爲主機地址,所以A類地址又少了一個可用網絡號。
10.2.5 本網絡本主機
- IP地址32bit全爲0的地址(0.0.0.0)表示的是本網絡本主機,這個IP地址在IP數據報中只能用做源IP地址,這發生在當設備啓動時但又不知道本身的IP地址狀況下。
- 在使用DHCP分配IP地址的網絡環境中,這樣的地址是很常見的,主機爲了得到一個可用的IP地址,就給DHCP服務器發送IP數據報,並用這樣的地址(0.0.0.0)做爲源地址,目的地址爲255.255.255.255(由於主機這時還不知道DHCP服務器的IP地址),而後DHCP服務器就會知道這個主機暫時沒有IP地址,那麼就會分配一個IP給這個主機。
10.3 UDP協議
- UDP 是User Datagram Protocol的簡稱, 中文名是用戶數據報協議
- 特色
- 無鏈接,即通訊時不須要建立鏈接(發送數據結束時也沒有鏈接能夠釋放)因此減少了開銷和發送數據前的時延;
- 不可靠,最大努力交付,不保證可靠交付,所以主機不須要維護複雜的鏈接狀態;
- 面向報文,只在應用層交下來的報文前增長了首部後就向下交付IP層;
- 無流量控制和無阻塞控制,即便網絡中存在阻塞,也不會影響發送端的發送頻率;
- 支持一對1、一對多、多對1、多對多的交互通訊;
- 首部開銷小,只有8個字節,它比TCP的20個字節的首部要短;
- 速度快,UDP沒有TCP的握手、確認、窗口、重傳、擁塞控制等機制,UDP是一個無狀態的傳輸協議,因此它在傳遞數據時很是快,即便在網絡擁塞的時候UDP也不會下降發送的數據。
- 應用環境
- 經常使用於實時視頻的傳輸,好比直播、網絡電話等,由於即便是出現了數據丟失的狀況,致使視頻卡幀,是能夠容忍的
10.4 TCP協議
- TCP是提供一種面向鏈接、可靠的字節流傳輸服務
- 與UDP的區別
- TCP面向鏈接、數據可靠。
- UDP運載的數據是以報文的形式,各個報文在網絡中互不相干傳輸,到達目標主機的順序是不同的,因此須要在應用層進行重裝。
- TCP採用數據流的形式傳輸,TCP協議會給每一個傳輸的字節進行編號,在傳輸的過程當中,發送方把數據的起始編號與長度放在TCP報文中,在接收方將全部數據按照編號組裝起來,而後返回一個確認,當全部數據接收完成後纔將數據遞交到應用層中。
- TCP的特性
- 鏈接機制:TCP是一個面向鏈接的協議
- 確認與重傳:一個完整的TCP傳輸必須有數據的交互。發送方發送數據後必須等待接收方的結果反饋,並開啓定時器,超時未接收到數據則認爲發送失敗,進行重發操做;接收方接收到數據後必須向發送方反饋結果。
- 緩衝機制:
- 發送方:應用程序的數據大小、類型都是不可預估的。在數據量很小時,TCP會將數據存儲在一個緩衝空間中,等到數據量足夠大的時候進行發送數據,直至確認接收方正確接收成功才刪除。
- 接收方:因爲網絡中傳輸的數據報到達接收方的時間是不同的,因此須要存起來進行重裝再交給應用層。
- 全雙工通訊:TCP是全雙工通訊。雙方都是主機,任意一方均可以斷開連接。
- 流量控制:
- 流量控制是一個速度匹配服務,即發送方的發送速率與接收方應用程序的讀取速率相匹配。
- TCP經過讓發送方維護一個稱爲接收窗口(receive window)的變量來提供流量控制。
- 接收窗口(rwnd),接收方會將此窗口值放在 TCP 報文的首部中的窗口字段,而後傳遞給發送方,這個窗口的大小是在發送數據的時候動態調整的。
- 若發送方收到的窗口值爲0,此時發送方仍是會進行發送只有一個字節的報文段。
- 差錯控制:TCP協議採用校驗和的方式來檢驗數據有效性。同時,接收方也會把接收到的數據報進行整理,重裝。
- 擁塞控制:在網絡中擁塞的狀況下調整自身的發送速度,這種形式對發送方的控制被稱爲擁塞控制(congestion control),採起的措施是限制發送方的發送速度。
10.5 端口號的概念
- TCP鏈接是兩個不一樣主機的應用鏈接,而傳輸層與上層協議是經過端口號進行識別的。
- 端口號的取值範圍爲:0~65535,不一樣端口號對應上層應用的不一樣線程
- 一臺主機可能只有一個IP地址,可是能夠有多個端口號
- 經過 IP地址+端口號 來區分主機不一樣的線程。
- 常見的TCP協議端口號有2一、5三、80等等
端口號 |
協議 |
說明 |
20/21 |
FTP |
文件傳輸協議,使得主機間能夠共享文件。 |
23 |
Telnet |
終端遠程登陸,它爲用戶提供了在本地計算機上完成遠程主機工做的能力。 |
25 |
SMTP |
簡單郵件傳輸協議,它幫助每臺計算機在發送或中轉信件時找到下一個目的地。 |
69 |
TFTP |
普通文件傳輸協議。 |
80 |
HTTP |
超文本傳輸協議,經過使用網頁瀏覽器、網絡爬蟲或者其它的工具,客戶端發起一個HTTP請求到服務器上指定端口(默認端口爲80),應答的服務器上存儲着一些資源,好比HTML文件和圖像,那麼就會返回這些數據到客戶端。 |
110 |
POP3 |
郵局協議版本3,本協議主要用於支持使用客戶端遠程管理在服務器上的電子郵件。 |
10.6 TCP報文段
- TCP報文段由 首部 + 數據域 組成

10.7 TCP創建鏈接
- TCP是一個面向鏈接的協議,鏈接俗稱握手。
- 三次握手創建鏈接
- 創建鏈接的過程是由客戶端發起,服務端等待客戶請求
- 第一步:客戶端向服務器端發送一個SYN報文段(只有首部,且SYN被置 1),初始序號(ISN)隨機選擇,假設爲A,ACK置 0。
- 第二步:服務器端收到SYN報文段,便知道客戶端須要請求握手,從SYN報文段中提取對應的信息,爲該TCP鏈接分配TCP緩存和變量,並向該客戶TCP發送容許鏈接的報文段(握手應答報文)。這個報文段只有首部,包含3個重要的信息:(創建客戶端-->服務端的鏈接)
- SYN與ACK標誌位1
- 將TCP報文段首部的確認序號字段設置爲A+1(這個A(ISN)是從握手請求報文中獲得)。
- 服務器隨機選擇本身的初始序號(ISN,注意此ISN是服務器端的ISN,假設爲B),並將其放置到TCP報文段首部的序號字段中。
- 第三步:客戶端接收到服務器端的握手應答後,會將SYN置 0,ACK置 1,確認序號置爲 B+1, 設置窗口值,能夠添加數據域的報文段發給服務器端。同時給該TCP鏈接分配緩存和變量。(創建服務端-->客戶端的鏈接)
- 參考圖:
10.8 TCP終止鏈接
- 創建鏈接須要三次握手,而終止鏈接須要四次揮手。
- 四次揮手終止鏈接
- 第一步:客戶端發出FIN報文段(首部FIN被置 1),序號假設爲C,ACK被置 1,可是確認序號是無效的。
- 第二步:當服務器端收到FIN報文段,它返回一個ACK報文段(終止鏈接應答),確認序號爲C+1。此時斷開客戶端-->服務器端的方向。
- 第三步:服務器端發出FIN報文段向客戶端請求終止鏈接,此時序號爲D,ACK被置 1,可是確認序號是無效的。
- 第四步:當客戶端收到FIN報文段,它返回一個ACK報文段(終止鏈接應答),確認序號爲D+1。此時斷開服務器端-->客戶端的鏈接。
- 參考圖
10.9 TCP狀態
- TCP協議的狀態以下:
- CLOSED:初始狀態,表示TCP鏈接是「關閉着的」或「未打開的」。
- LISTEN :表示服務器端的某個SOCKET處於監聽狀態,能夠接受客戶端的鏈接。
- SYN_RCVD :表示服務器接收到了來自客戶端請求鏈接的SYN報文。在正常狀況下,這個狀態是服務器端的SOCKET在創建TCP鏈接時的三次握手會話過程當中的一箇中間狀態,很短暫,基本上用netstat很難看到這種狀態,除非故意寫一個監測程序,將三次TCP握手過程當中最後一個ACK報文不予發送。當TCP鏈接處於此狀態時,再收到客戶端的ACK報文,它就會進入到ESTABLISHED狀態。
- SYN_SENT :這個狀態與SYN_RCVD狀態相呼應,當客戶端SOCKET執行connect()進行鏈接時,它首先發送SYN報文,而後隨即進入到SYN_SENT 狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
- ESTABLISHED :表示TCP鏈接已經成功創建。
- FIN_WAIT_1 :這個狀態得好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2兩種狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態其實是當SOCKET在ESTABLISHED狀態時,它想主動關閉鏈接,向對方發送了FIN報文,此時該SOCKET進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態。固然在實際的正常狀況下,不管對方處於任何種狀況下,都應該立刻迴應ACK報文,因此FIN_WAIT_1狀態通常是比較難見到的,而FIN_WAIT_2狀態有時仍能夠用netstat看到。
- FIN_WAIT_2 :上面已經解釋了這種狀態的由來,實際上FIN_WAIT_2狀態下的SOCKET表示半鏈接,即有一方調用close()主動要求關閉鏈接。注意:FIN_WAIT_2是沒有超時的(不像TIME_WAIT狀態),這種狀態下若是對方不關閉(不配合完成4次揮手過程),那這個 FIN_WAIT_2 狀態將一直保持到系統重啓,愈來愈多的FIN_WAIT_2狀態會致使內核crash。
- TIME_WAIT :表示收到了對方的FIN報文,併發送出了ACK報文。 TIME_WAIT狀態下的TCP鏈接會等待2*MSL(Max Segment Lifetime,最大分段生存期,指一個TCP報文在Internet上的最長生存時間。每一個具體的TCP協議實現都必須選擇一個肯定的MSL值,RFC 1122建議是2分鐘,但BSD傳統實現採用了30秒,Linux能夠在cat/proc/sys/net/ipv4/tcp_fin_timeout看到本機的這個值),而後便可回到CLOSED可用狀態了。若是FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,能夠直接進入到TIME_WAIT狀態,而無須通過FIN_WAIT_2狀態。(這種狀況應該就是四次揮手變成三次揮手的那種狀況)
- CLOSING :這種狀態在實際狀況中應該不多見,屬於一種比較罕見的例外狀態。正常狀況下,當一方發送FIN報文後,按理來講是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。可是CLOSING狀態表示一方發送FIN報文後,並無收到對方的ACK報文,反而卻也收到了對方的FIN報文。什麼狀況下會出現此種狀況呢?那就是當雙方几乎在同時close()一個SOCKET的話,就出現了雙方同時發送FIN報文的狀況,這是就會出現CLOSING狀態,表示雙方都正在關閉SOCKET鏈接。
- CLOSE_WAIT :表示正在等待關閉。怎麼理解呢?當對方close()一個SOCKET後發送FIN報文給本身,你的系統毫無疑問地將會迴應一個ACK報文給對方,此時TCP鏈接則進入到CLOSE_WAIT狀態。接下來呢,你須要檢查本身是否還有數據要發送給對方,若是沒有的話,那你也就能夠close()這個SOCKET併發送FIN報文給對方,即關閉本身到對方這個方向的鏈接。有數據的話則看程序的策略,繼續發送或丟棄。簡單地說,當你處於CLOSE_WAIT狀態下,須要完成的事情是等待你去關閉鏈接。
- LAST_ACK :當被動關閉的一方在發送FIN報文後,等待對方的ACK報文的時候,就處於LAST_ACK狀態。當收到對方的ACK報文後,也就能夠進入到CLOSED可用狀態了。
參考
* 野火