學(xué)完計(jì)算機(jī)網(wǎng)絡(luò),秋招穩(wěn)的一筆
大家好,我是程序汪呀,今天繼續(xù)來(lái)給大家分享三弟的面渣逆襲!
這次帶來(lái)的是計(jì)算機(jī)網(wǎng)絡(luò)六十二問(wèn),三萬(wàn)字,七十圖詳解,大概是全網(wǎng)最全的計(jì)算機(jī)網(wǎng)絡(luò)面試題。
建議大家收藏了慢慢看,秋招、春招、金九銀十、金三銀四沖!
基礎(chǔ)
1.說(shuō)下計(jì)算機(jī)網(wǎng)絡(luò)體系結(jié)構(gòu)
計(jì)算機(jī)網(wǎng)絡(luò)體系結(jié)構(gòu),一般有三種:OSI 七層模型、TCP/IP 四層模型、五層結(jié)構(gòu)。

簡(jiǎn)單說(shuō),OSI 是一個(gè)理論上的網(wǎng)絡(luò)通信模型,TCP/IP 是實(shí)際上的網(wǎng)絡(luò)通信模型,五層結(jié)構(gòu)就是為了介紹網(wǎng)絡(luò)原理而折中的網(wǎng)絡(luò)通信模型。
OSI 七層模型
OSI 七層模型是國(guó)際標(biāo)準(zhǔn)化組織(International Organization for Standardization)制定的一個(gè)用于計(jì)算機(jī)或通信系統(tǒng)間互聯(lián)的標(biāo)準(zhǔn)體系。
應(yīng)用層:通過(guò)應(yīng)用進(jìn)程之間的交互來(lái)完成特定網(wǎng)絡(luò)應(yīng)用,應(yīng)用層協(xié)議定義的是應(yīng)用進(jìn)程間通信和交互的規(guī)則,常見(jiàn)的協(xié)議有:HTTP FTP SMTP SNMP DNS. 表示層:數(shù)據(jù)的表示、安全、壓縮。確保一個(gè)系統(tǒng)的應(yīng)用層所發(fā)送的信息可以被另一個(gè)系統(tǒng)的應(yīng)用層讀取。 會(huì)話層:建立、管理、終止會(huì)話,是用戶應(yīng)用程序和網(wǎng)絡(luò)之間的接口。 運(yùn)輸層:提供源端與目的端之間提供可靠的透明數(shù)據(jù)傳輸,傳輸層協(xié)議為不同主機(jī)上運(yùn)行的進(jìn)程提供邏輯通信。 網(wǎng)絡(luò)層:將網(wǎng)絡(luò)地址翻譯成對(duì)應(yīng)的物理地址,實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇, 協(xié)議有 ICMP IGMP IP 等. 數(shù)據(jù)鏈路層:在物理層提供比特流服務(wù)的基礎(chǔ)上,建立相鄰結(jié)點(diǎn)之間的數(shù)據(jù)鏈路。 物理層:建立、維護(hù)、斷開(kāi)物理連接。
TCP/IP 四層模型
應(yīng)用層:對(duì)應(yīng)于 OSI 參考模型的(應(yīng)用層、表示層、會(huì)話層)。 傳輸層: 對(duì)應(yīng) OSI 的傳輸層,為應(yīng)用層實(shí)體提供端到端的通信功能,保證了數(shù)據(jù)包的順序傳送及數(shù)據(jù)的完整性。 網(wǎng)際層:對(duì)應(yīng)于 OSI 參考模型的網(wǎng)絡(luò)層,主要解決主機(jī)到主機(jī)的通信問(wèn)題。 網(wǎng)絡(luò)接口層:與 OSI 參考模型的數(shù)據(jù)鏈路層、物理層對(duì)應(yīng)。
五層體系結(jié)構(gòu)
應(yīng)用層:對(duì)應(yīng)于 OSI 參考模型的(應(yīng)用層、表示層、會(huì)話層)。 傳輸層:對(duì)應(yīng) OSI 參考模型的的傳輸層 網(wǎng)絡(luò)層:對(duì)應(yīng) OSI 參考模型的的網(wǎng)絡(luò)層 數(shù)據(jù)鏈路層:對(duì)應(yīng) OSI 參考模型的的數(shù)據(jù)鏈路層 物理層:對(duì)應(yīng) OSI 參考模型的的物理層。
2.說(shuō)一下每一層對(duì)應(yīng)的網(wǎng)絡(luò)協(xié)議有哪些?
一張表格總結(jié)常見(jiàn)網(wǎng)絡(luò)協(xié)議:

3.那么數(shù)據(jù)在各層之間是怎么傳輸?shù)哪兀?span style="display: none;">
對(duì)于發(fā)送方而言,從上層到下層層層包裝,對(duì)于接收方而言,從下層到上層,層層解開(kāi)包裝。
發(fā)送方的應(yīng)用進(jìn)程向接收方的應(yīng)用進(jìn)程傳送數(shù)據(jù) AP 先將數(shù)據(jù)交給本主機(jī)的應(yīng)用層,應(yīng)用層加上本層的控制信息 H5 就變成了下一層的數(shù)據(jù)單元 傳輸層收到這個(gè)數(shù)據(jù)單元后,加上本層的控制信息 H4,再交給網(wǎng)絡(luò)層,成為網(wǎng)絡(luò)層的數(shù)據(jù)單元 到了數(shù)據(jù)鏈路層,控制信息被分成兩部分,分別加到本層數(shù)據(jù)單元的首部(H2)和尾部(T2) 最后的物理層,進(jìn)行比特流的傳輸

這個(gè)過(guò)程類似寫(xiě)信,寫(xiě)一封信,每到一層,就加一個(gè)信封,寫(xiě)一些地址的信息。到了目的地之后,又一層層解封,傳向下一個(gè)目的地。
網(wǎng)絡(luò)綜合
4.從瀏覽器地址欄輸入 url 到顯示主頁(yè)的過(guò)程?
這道題,大概的過(guò)程比較簡(jiǎn)單,但是有很多點(diǎn)可以細(xì)挖:DNS 解析、TCP 三次握手、HTTP 報(bào)文格式、TCP 四次揮手等等。
DNS 解析:將域名解析成對(duì)應(yīng)的 IP 地址。 TCP 連接:與服務(wù)器通過(guò)三次握手,建立 TCP 連接 向服務(wù)器發(fā)送 HTTP 請(qǐng)求 服務(wù)器處理請(qǐng)求,返回 HTTp 響應(yīng) 瀏覽器解析并渲染頁(yè)面 斷開(kāi)連接:TCP 四次揮手,連接結(jié)束
我們以輸入 www.baidu.com 為例:

各個(gè)過(guò)程都使用了哪些協(xié)議?

5.說(shuō)說(shuō) DNS 的解析過(guò)程?
DNS,英文全稱是 domain name system,域名解析系統(tǒng),它的作用也很明確,就是域名和 IP 相互映射。
DNS 的解析過(guò)程如下圖:

假設(shè)你要查詢 www.baidu.com 的 IP 地址:
首先會(huì)查找瀏覽器的緩存,看看是否能找到www.baidu.com對(duì)應(yīng)的 IP 地址,找到就直接返回;否則進(jìn)行下一步。 將請(qǐng)求發(fā)往給本地 DNS 服務(wù)器,如果查找到也直接返回,否則繼續(xù)進(jìn)行下一步;

本地 DNS 服務(wù)器向根域名服務(wù)器發(fā)送請(qǐng)求,根域名服務(wù)器返回負(fù)責(zé) com的頂級(jí)域名服務(wù)器的 IP 地址的列表。本地 DNS 服務(wù)器再向其中一個(gè)負(fù)責(zé) com的頂級(jí)域名服務(wù)器發(fā)送一個(gè)請(qǐng)求,返回負(fù)責(zé)baidu.com的權(quán)限域名服務(wù)器的 IP 地址列表。本地 DNS 服務(wù)器再向其中一個(gè)權(quán)限域名服務(wù)器發(fā)送一個(gè)請(qǐng)求,返回www.baidu.com所對(duì)應(yīng)的 IP 地址。
6.說(shuō)說(shuō) WebSocket 與 Socket 的區(qū)別?
Socket 其實(shí)就是等于 IP 地址 + 端口 + 協(xié)議。
具體來(lái)說(shuō),Socket 是一套標(biāo)準(zhǔn),它完成了對(duì) TCP/IP 的高度封裝,屏蔽網(wǎng)絡(luò)細(xì)節(jié),以方便開(kāi)發(fā)者更好地進(jìn)行網(wǎng)絡(luò)編程。
WebSocket 是一個(gè)持久化的協(xié)議,它是伴隨 H5 而出的協(xié)議,用來(lái)解決 http 不支持持久化連接的問(wèn)題。 Socket 一個(gè)是網(wǎng)編編程的標(biāo)準(zhǔn)接口,而 WebSocket 則是應(yīng)用層通信協(xié)議。
7.說(shuō)一下你了解的端口及對(duì)應(yīng)的服務(wù)?

HTTP
8.說(shuō)說(shuō) HTTP 常用的狀態(tài)碼及其含義?
HTTP 狀態(tài)碼首先應(yīng)該知道個(gè)大概的分類:
1XX:信息性狀態(tài)碼 2XX:成功狀態(tài)碼 3XX:重定向狀態(tài)碼 4XX:客戶端錯(cuò)誤狀態(tài)碼 5XX:服務(wù)端錯(cuò)誤狀態(tài)碼
幾個(gè)常用的,面試之外,也應(yīng)該記住:

之前寫(xiě)過(guò)一篇:程序員五一被拉去相親,結(jié)果徹底搞懂了 HTTP 常用狀態(tài)碼,還比較有意思,可以看看。
說(shuō)一下 301 和 302 的區(qū)別?
301:永久性移動(dòng),請(qǐng)求的資源已被永久移動(dòng)到新位置。服務(wù)器返回此響應(yīng)時(shí),會(huì)返回新的資源地址。 302:臨時(shí)性性移動(dòng),服務(wù)器從另外的地址響應(yīng)資源,但是客戶端還應(yīng)該使用這個(gè)地址。
用一個(gè)比喻,301 就是嫁人的新垣結(jié)衣,302 就是有男朋友的長(zhǎng)澤雅美。
9.HTTP 有哪些請(qǐng)求方式?

其中,POST、DELETE、PUT、GET 的含義分別對(duì)應(yīng)我們最熟悉的增、刪、改、查。
10.說(shuō)?下 GET 和 POST 的區(qū)別?
可以從以下幾個(gè)方面來(lái)說(shuō)明 GET 和 POST 的區(qū)別:

從 HTTP 報(bào)文層面來(lái)看,GET 請(qǐng)求將信息放在 URL,POST 將請(qǐng)求信息放在請(qǐng)求體中。這一點(diǎn)使得 GET 請(qǐng)求攜帶的數(shù)據(jù)量有限,因?yàn)?URL 本身是有長(zhǎng)度限制的,而 POST 請(qǐng)求的數(shù)據(jù)存放在報(bào)文體中,因此對(duì)大小沒(méi)有限制。而且從形式上看,GET 請(qǐng)求把數(shù)據(jù)放 URL 上不太安全,而 POST 請(qǐng)求把數(shù)據(jù)放在請(qǐng)求體里想比較而言安全一些。 從數(shù)據(jù)庫(kù)層面來(lái)看,GET 符合冪等性和安全性,而 POST 請(qǐng)求不符合。這個(gè)其實(shí)和 GET/POST 請(qǐng)求的作用有關(guān)。按照 HTTP 的約定,GET 請(qǐng)求用于查看信息,不會(huì)改變服務(wù)器上的信息;而 POST 請(qǐng)求用來(lái)改變服務(wù)器上的信息。正因?yàn)?GET 請(qǐng)求只查看信息,不改變信息,對(duì)數(shù)據(jù)庫(kù)的一次或多次操作獲得的結(jié)果是一致的,認(rèn)為它符合冪等性。安全性是指對(duì)數(shù)據(jù)庫(kù)操作沒(méi)有改變數(shù)據(jù)庫(kù)中的數(shù)據(jù)。 從其他層面來(lái)看,GET 請(qǐng)求能夠被緩存,GET 請(qǐng)求能夠保存在瀏覽器的瀏覽記錄里,GET 請(qǐng)求的 URL 能夠保存為瀏覽器書(shū)簽。這些都是 POST 請(qǐng)求所不具備的。緩存是 GET 請(qǐng)求被廣泛應(yīng)用的根本,他能夠被緩存也是因?yàn)樗膬绲刃院桶踩裕朔祷亟Y(jié)果沒(méi)有其他多余的動(dòng)作,因此絕大部分的 GET 請(qǐng)求都被 CDN 緩存起來(lái)了,大大減少了 Web 服務(wù)器的負(fù)擔(dān)。
11.GET 的長(zhǎng)度限制是多少?
HTTP 中的 GET 方法是通過(guò) URL 傳遞數(shù)據(jù)的,但是 URL 本身其實(shí)并沒(méi)有對(duì)數(shù)據(jù)的長(zhǎng)度進(jìn)行限制,真正限制 GET 長(zhǎng)度的是瀏覽器。
例如 IE 瀏覽器對(duì) URL 的最大限制是 2000 多個(gè)字符,大概 2kb 左右,像 Chrome、Firefox 等瀏覽器支持的 URL 字符數(shù)更多,其中 FireFox 中 URL 的最大長(zhǎng)度限制是 65536 個(gè)字符,Chrome 則是 8182 個(gè)字符。
這個(gè)長(zhǎng)度限制也不是針對(duì)數(shù)據(jù)部分,而是針對(duì)整個(gè) URL。
12.HTTP 請(qǐng)求的過(guò)程與原理?
HTTP 協(xié)議定義了瀏覽器怎么向服務(wù)器請(qǐng)求文檔,以及服務(wù)器怎么把文檔傳給瀏覽器。

每個(gè)服務(wù)器都有一個(gè)進(jìn)程,它不斷監(jiān)聽(tīng) TCP 的端口 80,以便發(fā)現(xiàn)是否有瀏覽器向它發(fā)出連接建立請(qǐng)求 監(jiān)聽(tīng)到連接請(qǐng)求,就會(huì)建立 TCP 連接 瀏覽器向服務(wù)器發(fā)出瀏覽某個(gè)頁(yè)面的請(qǐng)求,服務(wù)器接著就返回所請(qǐng)求的頁(yè)面作為響應(yīng) 最后,釋放 TCP 連接
在瀏覽器和服務(wù)器之間的請(qǐng)求和響應(yīng)的交互,必須按照規(guī)定的格式和遵循一定的規(guī)則,這些格式和規(guī)則就是超文本傳輸協(xié)議 HTTP。
PS:這道題和上面瀏覽器輸入網(wǎng)址發(fā)生了什么那道題大差不差。
13.說(shuō)一下 HTTP 的報(bào)文結(jié)構(gòu)?
HTTP 報(bào)文有兩種,HTTP 請(qǐng)求報(bào)文和 HTTP 響應(yīng)報(bào)文:
HTTP 請(qǐng)求報(bào)文
HTTP 請(qǐng)求報(bào)文的格式如下:
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
HTTP 請(qǐng)求報(bào)文的第一行叫做請(qǐng)求行,后面的行叫做首部行,首部行后還可以跟一個(gè)實(shí)體主體。請(qǐng)求首部之后有一個(gè)空行,這個(gè)空行不能省略,它用來(lái)劃分首部與實(shí)體。
請(qǐng)求行包含三個(gè)字段:
方法字段:包括 POST、GET 等請(qǐng)方法。 URL 字段 HTTP 版本字段。
HTTP 響應(yīng)報(bào)文
HTTP 響應(yīng)報(bào)文的格式如下:
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
HTTP 響應(yīng)報(bào)文的第一行叫做狀態(tài)行,后面的行是首部行,最后是實(shí)體主體。
狀態(tài)行包含了三個(gè)字段:協(xié)議版本字段、狀態(tài)碼和相應(yīng)的狀態(tài)信息。
實(shí)體部分是報(bào)文的主要部分,它包含了所請(qǐng)求的對(duì)象。
首部行首部可以分為四種首部,請(qǐng)求首部、響應(yīng)首部、通用首部和實(shí)體首部。通用首部和實(shí)體首部在請(qǐng)求報(bào)文和響應(yīng)報(bào)文中都可以設(shè)置,區(qū)別在于請(qǐng)求首部和響應(yīng)首部。
常見(jiàn)的請(qǐng)求首部有 Accept 可接收媒體資源的類型、Accept-Charset 可接收的字符集、Host 請(qǐng)求的主機(jī)名。
常見(jiàn)的響應(yīng)首部有 ETag 資源的匹配信息,Location 客戶端重定向的 URI。
常見(jiàn)的通用首部有 Cache-Control 控制緩存策略、Connection 管理持久連接。
常見(jiàn)的實(shí)體首部有 Content-Length 實(shí)體主體的大小、Expires 實(shí)體主體的過(guò)期時(shí)間、Last-Modified 資源的最后修改時(shí)間。
14.URI 和 URL 有什么區(qū)別?

URI,統(tǒng)一資源標(biāo)識(shí)符(Uniform Resource Identifier, URI),標(biāo)識(shí)的是 Web 上每一種可用的資源,如 HTML 文檔、圖像、視頻片段、程序等都是由一個(gè) URI 進(jìn)行標(biāo)識(shí)的。 URL,統(tǒng)一資源定位符(Uniform Resource Location),它是 URI 的一種子集,主要作用是提供資源的路徑。
它們的主要區(qū)別在于,URL 除了提供了資源的標(biāo)識(shí),還提供了資源訪問(wèn)的方式。這么比喻,URI 像是身份證,可以唯一標(biāo)識(shí)一個(gè)人,而 URL 更像一個(gè)住址,可以通過(guò) URL 找到這個(gè)人——人類住址協(xié)議://地球/中國(guó)/北京市/海淀區(qū)/xx 職業(yè)技術(shù)學(xué)院/14 號(hào)宿舍樓/525 號(hào)寢/張三.男。
15.說(shuō)下 HTTP/1.0,1.1,2.0 的區(qū)別?
關(guān)鍵需要記住 HTTP/1.0 默認(rèn)是短連接,可以強(qiáng)制開(kāi)啟,HTTP/1.1 默認(rèn)長(zhǎng)連接,HTTP/2.0 采用多路復(fù)用。
HTTP/1.0
默認(rèn)使用短連接,每次請(qǐng)求都需要建立一個(gè) TCP 連接。它可以設(shè)置 Connection: keep-alive這個(gè)字段,強(qiáng)制開(kāi)啟長(zhǎng)連接。
HTTP/1.1
引入了持久連接,即 TCP 連接默認(rèn)不關(guān)閉,可以被多個(gè)請(qǐng)求復(fù)用。 分塊傳輸編碼,即服務(wù)端每產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊,用” 流模式” 取代” 緩存模式”。 管道機(jī)制,即在同一個(gè) TCP 連接里面,客戶端可以同時(shí)發(fā)送多個(gè)請(qǐng)求。
HTTP/2.0
二進(jìn)制協(xié)議,1.1 版本的頭信息是文本(ASCII 編碼),數(shù)據(jù)體可以是文本或者二進(jìn)制;2.0 中,頭信息和數(shù)據(jù)體都是二進(jìn)制。 完全多路復(fù)用,在一個(gè)連接里,客戶端和瀏覽器都可以同時(shí)發(fā)送多個(gè)請(qǐng)求或回應(yīng),而且不用按照順序一一對(duì)應(yīng)。 報(bào)頭壓縮,HTTP 協(xié)議不帶有狀態(tài),每次請(qǐng)求都必須附上所有信息。Http/2.0 引入了頭信息壓縮機(jī)制,使用 gzip 或 compress 壓縮后再發(fā)送。 服務(wù)端推送,允許服務(wù)器未經(jīng)請(qǐng)求,主動(dòng)向客戶端發(fā)送資源。
16.HTTP/3 了解嗎?
HTTP/3 主要有兩大變化,傳輸層基于 UDP、使用QUIC 保證 UDP 可靠性。
HTTP/2 存在的一些問(wèn)題,比如重傳等等,都是由于 TCP 本身的特性導(dǎo)致的,所以 HTTP/3 在 QUIC 的基礎(chǔ)上進(jìn)行發(fā)展而來(lái),QUIC(Quick UDP Connections)直譯為快速 UDP 網(wǎng)絡(luò)連接,底層使用 UDP 進(jìn)行數(shù)據(jù)傳輸。
HTTP/3 主要有這些特點(diǎn):
使用 UDP 作為傳輸層進(jìn)行通信 在 UDP 的基礎(chǔ)上 QUIC 協(xié)議保證了 HTTP/3 的安全性,在傳輸?shù)倪^(guò)程中就完成了 TLS 加密握手 HTTPS 要建??個(gè)連接,要花費(fèi) 6 次交互,先是建?三次握?,然后是 TLS/1.3 的三次握?。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 3 次,減少了交互次數(shù)。 QUIC 有??的?套機(jī)制可以保證傳輸?shù)目煽啃缘摹.?dāng)某個(gè)流發(fā)?丟包時(shí),只會(huì)阻塞這個(gè)流,其他流不會(huì)受到影響。
我們拿一張圖看一下 HTTP 協(xié)議的變遷:

17.HTTP 如何實(shí)現(xiàn)長(zhǎng)連接?在什么時(shí)候會(huì)超時(shí)?
什么是 HTTP 的長(zhǎng)連接?
HTTP 分為長(zhǎng)連接和短連接,本質(zhì)上說(shuō)的是 TCP 的長(zhǎng)短連接。TCP 連接是一個(gè)雙向的通道,它是可以保持一段時(shí)間不關(guān)閉的,因此 TCP 連接才具有真正的長(zhǎng)連接和短連接這一說(shuō)法。 TCP 長(zhǎng)連接可以復(fù)用一個(gè) TCP 連接,來(lái)發(fā)起多次的 HTTP 請(qǐng)求,這樣就可以減少資源消耗,比如一次請(qǐng)求 HTML,如果是短連接的話,可能還需要請(qǐng)求后續(xù)的 JS/CSS。
如何設(shè)置長(zhǎng)連接?
通過(guò)在頭部(請(qǐng)求和響應(yīng)頭)設(shè)置 Connection 字段指定為keep-alive,HTTP/1.0 協(xié)議支持,但是是默認(rèn)關(guān)閉的,從 HTTP/1.1 以后,連接默認(rèn)都是長(zhǎng)連接。
在什么時(shí)候會(huì)超時(shí)呢?
HTTP 一般會(huì)有 httpd 守護(hù)進(jìn)程,里面可以設(shè)置 keep-alive timeout,當(dāng) tcp 連接閑置超過(guò)這個(gè)時(shí)間就會(huì)關(guān)閉,也可以在 HTTP 的 header 里面設(shè)置超時(shí)時(shí)間 TCP 的 keep-alive 包含三個(gè)參數(shù),支持在系統(tǒng)內(nèi)核的 net.ipv4 里面設(shè)置;當(dāng) TCP 連接之后,閑置了 tcp_keepalive_time,則會(huì)發(fā)生偵測(cè)包,如果沒(méi)有收到對(duì)方的 ACK,那么會(huì)每隔 tcp_keepalive_intvl 再發(fā)一次,直到發(fā)送了 tcp_keepalive_probes,就會(huì)丟棄該連接。
1. tcp_keepalive_intvl = 15
2. tcp_keepalive_probes = 5
3. tcp_keepalive_time = 1800
18.說(shuō)說(shuō) HTTP 與 HTTPS 有哪些區(qū)別?
HTTP 是超?本傳輸協(xié)議,信息是明?傳輸,存在安全?險(xiǎn)的問(wèn)題。HTTPS 則解決 HTTP 不安全的缺陷,在 TCP 和 HTTP ?絡(luò)層之間加?了 SSL/TLS 安全協(xié)議,使得報(bào)?能夠加密傳輸。 HTTP 連接建?相對(duì)簡(jiǎn)單, TCP 三次握?之后便可進(jìn)? HTTP 的報(bào)?傳輸。? HTTPS 在 TCP 三次握?之后,還需進(jìn)? SSL/TLS 的握?過(guò)程,才可進(jìn)?加密報(bào)?傳輸。 HTTP 的端?號(hào)是 80,HTTPS 的端?號(hào)是 443。 HTTPS 協(xié)議需要向 CA(證書(shū)權(quán)威機(jī)構(gòu))申請(qǐng)數(shù)字證書(shū),來(lái)保證服務(wù)器的身份是可信的。
19.為什么要用 HTTPS?解決了哪些問(wèn)題?
因?yàn)?HTTP 是明?傳輸,存在安全上的風(fēng)險(xiǎn):
竊聽(tīng)?險(xiǎn),?如通信鏈路上可以獲取通信內(nèi)容,用戶賬號(hào)被盜。
篡改?險(xiǎn),?如強(qiáng)制植?垃圾?告,視覺(jué)污染。
冒充?險(xiǎn),?如冒充淘寶?站,用戶金錢損失。

所以引入了 HTTPS,HTTPS 在 HTTP 與 TCP 層之間加?了 SSL/TLS 協(xié)議,可以很好的解決了這些風(fēng)險(xiǎn):
信息加密:交互信息?法被竊取。 校驗(yàn)機(jī)制:?法篡改通信內(nèi)容,篡改了就不能正常顯示。 身份證書(shū):能證明淘寶是真淘寶。
所以 SSL/TLS 協(xié)議是能保證通信是安全的。
20.HTTPS 工作流程是怎樣的?
這道題有幾個(gè)要點(diǎn):公私鑰、數(shù)字證書(shū)、加密、對(duì)稱加密、非對(duì)稱加密。
HTTPS 主要工作流程:
客戶端發(fā)起 HTTPS 請(qǐng)求,連接到服務(wù)端的 443 端口。 服務(wù)端有一套數(shù)字證書(shū)(證書(shū)內(nèi)容有公鑰、證書(shū)頒發(fā)機(jī)構(gòu)、失效日期等)。 服務(wù)端將自己的數(shù)字證書(shū)發(fā)送給客戶端(公鑰在證書(shū)里面,私鑰由服務(wù)器持有)。 客戶端收到數(shù)字證書(shū)之后,會(huì)驗(yàn)證證書(shū)的合法性。如果證書(shū)驗(yàn)證通過(guò),就會(huì)生成一個(gè)隨機(jī)的對(duì)稱密鑰,用證書(shū)的公鑰加密。 客戶端將公鑰加密后的密鑰發(fā)送到服務(wù)器。 服務(wù)器接收到客戶端發(fā)來(lái)的密文密鑰之后,用自己之前保留的私鑰對(duì)其進(jìn)行非對(duì)稱解密,解密之后就得到客戶端的密鑰,然后用客戶端密鑰對(duì)返回?cái)?shù)據(jù)進(jìn)行對(duì)稱加密,醬紫傳輸?shù)臄?shù)據(jù)都是密文啦。 服務(wù)器將加密后的密文返回到客戶端。 客戶端收到后,用自己的密鑰對(duì)其進(jìn)行對(duì)稱解密,得到服務(wù)器返回的數(shù)據(jù)。

這里還畫(huà)了一張更詳盡的圖:

21.客戶端怎么去校驗(yàn)證書(shū)的合法性?
首先,服務(wù)端的證書(shū)從哪來(lái)的呢?
為了讓服務(wù)端的公鑰被?家信任,服務(wù)端的證書(shū)都是由 CA (_Certificate Authority_,證書(shū)認(rèn)證機(jī)構(gòu))簽名的,CA 就是?絡(luò)世界?的公安局、公證中?,具有極?的可信度,所以由它來(lái)給各個(gè)公鑰簽名,信任的??簽發(fā)的證書(shū),那必然證書(shū)也是被信任的。

CA 簽發(fā)證書(shū)的過(guò)程,如上圖左邊部分:
?先 CA 會(huì)把持有者的公鑰、?途、頒發(fā)者、有效時(shí)間等信息打成?個(gè)包,然后對(duì)這些信息進(jìn)? Hash 計(jì)算,得到?個(gè) Hash 值; 然后 CA 會(huì)使???的私鑰將該 Hash 值加密,?成 Certificate Signature,也就是 CA 對(duì)證書(shū)做了簽名; 最后將 Certificate Signature 添加在?件證書(shū)上,形成數(shù)字證書(shū);
客戶端校驗(yàn)服務(wù)端的數(shù)字證書(shū)的過(guò)程,如上圖右邊部分:
?先客戶端會(huì)使?同樣的 Hash 算法獲取該證書(shū)的 Hash 值 H1; 通常瀏覽器和操作系統(tǒng)中集成了 CA 的公鑰信息,瀏覽器收到證書(shū)后可以使? CA 的公鑰解密 Certificate Signature 內(nèi)容,得到?個(gè) Hash 值 H2 ; 最后?較 H1 和 H2,如果值相同,則為可信賴的證書(shū),否則則認(rèn)為證書(shū)不可信。
假如在 HTTPS 的通信過(guò)程中,中間人篡改了證書(shū)原文,由于他沒(méi)有 CA 機(jī)構(gòu)的私鑰,所以 CA 公鑰解密的內(nèi)容就不一致。
22.如何理解 HTTP 協(xié)議是無(wú)狀態(tài)的?
這個(gè)無(wú)狀態(tài)的的狀態(tài)值的是什么?是客戶端的狀態(tài),所以字面意思,就是 HTTP 協(xié)議中服務(wù)端不會(huì)保存客戶端的任何信息。
比如當(dāng)瀏覽器第一次發(fā)送請(qǐng)求給服務(wù)器時(shí),服務(wù)器響應(yīng)了;如果同個(gè)瀏覽器發(fā)起第二次請(qǐng)求給服務(wù)器時(shí),它還是會(huì)響應(yīng),但是呢,服務(wù)器不知道你就是剛才的那個(gè)瀏覽器。
那有什么辦法記錄狀態(tài)呢?
主要有兩個(gè)辦法,Session 和 Cookie。
23.說(shuō)說(shuō) Session 和 Cookie 有什么聯(lián)系和區(qū)別?
先來(lái)看看什么是 Session 和 Cookie :
Cookie 是保存在客戶端的一小塊文本串的數(shù)據(jù)。客戶端向服務(wù)器發(fā)起請(qǐng)求時(shí),服務(wù)端會(huì)向客戶端發(fā)送一個(gè) Cookie,客戶端就把 Cookie 保存起來(lái)。在客戶端下次向同一服務(wù)器再發(fā)起請(qǐng)求時(shí),Cookie 被攜帶發(fā)送到服務(wù)器。服務(wù)端可以根據(jù)這個(gè) Cookie 判斷用戶的身份和狀態(tài)。 Session 指的就是服務(wù)器和客戶端一次會(huì)話的過(guò)程。它是另一種記錄客戶狀態(tài)的機(jī)制。不同的是 cookie 保存在客戶端瀏覽器中,而 session 保存在服務(wù)器上。客戶端瀏覽器訪問(wèn)服務(wù)器的時(shí)候,服務(wù)器把客戶端信息以某種形式記錄在服務(wù)器上,這就是 session。客戶端瀏覽器再次訪問(wèn)時(shí)只需要從該 session 中查找用戶的狀態(tài)。

Session 和 Cookie 到底有什么不同呢?
存儲(chǔ)位置不一樣,Cookie 保存在客戶端,Session 保存在服務(wù)器端。 存儲(chǔ)數(shù)據(jù)類型不一樣,Cookie 只能保存 ASCII,Session 可以存任意數(shù)據(jù)類型,一般情況下我們可以在 Session 中保持一些常用變量信息,比如說(shuō) UserId 等。 有效期不同,Cookie 可設(shè)置為長(zhǎng)時(shí)間保持,比如我們經(jīng)常使用的默認(rèn)登錄功能,Session 一般有效時(shí)間較短,客戶端關(guān)閉或者 Session 超時(shí)都會(huì)失效。 隱私策略不同,Cookie 存儲(chǔ)在客戶端,比較容易遭到不法獲取,早期有人將用戶的登錄名和密碼存儲(chǔ)在 Cookie 中導(dǎo)致信息被竊取;Session 存儲(chǔ)在服務(wù)端,安全性相對(duì) Cookie 要好一些。 存儲(chǔ)大小不同, 單個(gè) Cookie 保存的數(shù)據(jù)不能超過(guò) 4K,Session 可存儲(chǔ)數(shù)據(jù)遠(yuǎn)高于 Cookie。
Session 和 Cookie 有什么關(guān)聯(lián)呢?
可以使用 Cookie 記錄 Session 的標(biāo)識(shí)。

用戶第一次請(qǐng)求服務(wù)器時(shí),服務(wù)器根據(jù)用戶提交的信息,創(chuàng)建對(duì)應(yīng)的 Session,請(qǐng)求返回時(shí)將此 Session 的唯一標(biāo)識(shí)信息 SessionID 返回給瀏覽器,瀏覽器接收到服務(wù)器返回的 SessionID 信息后,會(huì)將此信息存入 Cookie 中,同時(shí) Cookie 記錄此 SessionID 是屬于哪個(gè)域名。 當(dāng)用戶第二次訪問(wèn)服務(wù)器時(shí),請(qǐng)求會(huì)自動(dòng)判斷此域名下是否存在 Cookie 信息,如果存在,則自動(dòng)將 Cookie 信息也發(fā)送給服務(wù)端,服務(wù)端會(huì)從 Cookie 中獲取 SessionID,再根據(jù) SessionID 查找對(duì)應(yīng)的 Session 信息,如果沒(méi)有找到,說(shuō)明用戶沒(méi)有登錄或者登錄失效,如果找到 Session 證明用戶已經(jīng)登錄可執(zhí)行后面操作。
分布式環(huán)境下 Session 怎么處理呢?
分布式環(huán)境下,客戶端請(qǐng)求經(jīng)過(guò)負(fù)載均衡,可能會(huì)分配到不同的服務(wù)器上,假如一個(gè)用戶的請(qǐng)求兩次沒(méi)有落到同一臺(tái)服務(wù)器上,那么在新的服務(wù)器上就沒(méi)有記錄用戶狀態(tài)的 Session。
這時(shí)候怎么辦呢?
可以使用 Redis 等分布式緩存來(lái)存儲(chǔ) Session,在多臺(tái)服務(wù)器之間共享。

客戶端無(wú)法使用 Cookie 怎么辦?
有可能客戶端無(wú)法使用 Cookie,比如瀏覽器禁用 Cookie,或者客戶端是安卓、IOS 等等。
這時(shí)候怎么辦?SessionID 怎么存?怎么傳給服務(wù)端呢?
首先是 SessionID 的存儲(chǔ),可以使用客戶端的本地存儲(chǔ),比如瀏覽器的 sessionStorage。
接下來(lái)怎么傳呢?
拼接到 URL 里:直接把 SessionID 作為 URL 的請(qǐng)求參數(shù) 放到請(qǐng)求頭里:把 SessionID 放到請(qǐng)求的 Header 里,比較常用。
TCP
24.詳細(xì)說(shuō)一下 TCP 的三次握手機(jī)制
PS:TCP 三次握手是最重要的知識(shí)點(diǎn),一定要熟悉到問(wèn)到即送分。
TCP 提供面向連接的服務(wù),在傳送數(shù)據(jù)前必須建立連接,TCP 連接是通過(guò)三次握手建立的。

三次握手的過(guò)程:
最開(kāi)始,客戶端和服務(wù)端都處于 CLOSE 狀態(tài),服務(wù)端監(jiān)聽(tīng)客戶端的請(qǐng)求,進(jìn)入 LISTEN 狀態(tài)
客戶端端發(fā)送連接請(qǐng)求,第一次握手 (SYN=1, seq=x),發(fā)送完畢后,客戶端就進(jìn)入 SYN_SENT 狀態(tài)
服務(wù)端確認(rèn)連接,第二次握手 (SYN=1, ACK=1, seq=y, ACKnum=x+1), 發(fā)送完畢后,服務(wù)器端就進(jìn)入 SYN_RCV 狀態(tài)。
客戶端收到服務(wù)端的確認(rèn)之后,再次向服務(wù)端確認(rèn),這就是**第三次握手 **(ACK=1,ACKnum=y+1),發(fā)送完畢后,客戶端進(jìn)入 ESTABLISHED 狀態(tài),當(dāng)服務(wù)器端接收到這個(gè)包時(shí),也進(jìn)入 ESTABLISHED 狀態(tài)。
TCP 三次握手通俗比喻:
在二十年前的農(nóng)村,電話沒(méi)有普及,手機(jī)就更不用說(shuō)了,所以,通信基本靠吼。
老張和老王是鄰居,這天老張下地了,結(jié)果家里有事,熱心的鄰居老王趕緊跑到村口,開(kāi)始叫喚老王。
老王:老張唉!我是老王,你能聽(tīng)到嗎? 老張一聽(tīng),是老王的聲音:老王老王,我是老張,我能聽(tīng)到,你能聽(tīng)到嗎? 老王一聽(tīng),嗯,沒(méi)錯(cuò),是老張:老張,我聽(tīng)到了,我有事要跟你說(shuō)。
"你老婆要生了,趕緊回家吧!"
老張風(fēng)風(fēng)火火地趕回家,老婆順利地生了個(gè)帶把的大胖小子。握手的故事充滿了幸福和美滿。

25.TCP 握手為什么是三次,為什么不能是兩次?不能是四次?
為什么不能是兩次?
為了防止服務(wù)器端開(kāi)啟一些無(wú)用的連接增加服務(wù)器開(kāi)銷 防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯(cuò)誤。
由于網(wǎng)絡(luò)傳輸是有延時(shí)的(要通過(guò)網(wǎng)絡(luò)光纖和各種中間代理服務(wù)器),在傳輸?shù)倪^(guò)程中,比如客戶端發(fā)起了 SYN=1 的第一次握手。
如果服務(wù)器端就直接創(chuàng)建了這個(gè)連接并返回包含 SYN、ACK 和 Seq 等內(nèi)容的數(shù)據(jù)包給客戶端,這個(gè)數(shù)據(jù)包因?yàn)榫W(wǎng)絡(luò)傳輸?shù)脑騺G失了,丟失之后客戶端就一直沒(méi)有接收到服務(wù)器返回的數(shù)據(jù)包。
如果沒(méi)有第三次握手告訴服務(wù)器端客戶端收的到服務(wù)器端傳輸?shù)臄?shù)據(jù)的話,服務(wù)器端是不知道客戶端有沒(méi)有接收到服務(wù)器端返回的信息的。
服務(wù)端就認(rèn)為這個(gè)連接是可用的,端口就一直開(kāi)著,等到客戶端因超時(shí)重新發(fā)出請(qǐng)求時(shí),服務(wù)器就會(huì)重新開(kāi)啟一個(gè)端口連接。這樣一來(lái),就會(huì)有很多無(wú)效的連接端口白白地開(kāi)著,導(dǎo)致資源的浪費(fèi)。

還有一種情況是已經(jīng)失效的客戶端發(fā)出的請(qǐng)求信息,由于某種原因傳輸?shù)搅朔?wù)器端,服務(wù)器端以為是客戶端發(fā)出的有效請(qǐng)求,接收后產(chǎn)生錯(cuò)誤。

所以我們需要“第三次握手”來(lái)確認(rèn)這個(gè)過(guò)程:
通過(guò)第三次握手的數(shù)據(jù)告訴服務(wù)端,客戶端有沒(méi)有收到服務(wù)器“第二次握手”時(shí)傳過(guò)去的數(shù)據(jù),以及這個(gè)連接的序號(hào)是不是有效的。若發(fā)送的這個(gè)數(shù)據(jù)是“收到且沒(méi)有問(wèn)題”的信息,接收后服務(wù)器就正常建立 TCP 連接,否則建立 TCP 連接失敗,服務(wù)器關(guān)閉連接端口。由此減少服務(wù)器開(kāi)銷和接收到失效請(qǐng)求發(fā)生的錯(cuò)誤。
為什么不是四次?
簡(jiǎn)單說(shuō),就是三次揮手已經(jīng)足夠創(chuàng)建可靠的連接,沒(méi)有必要再多一次握手導(dǎo)致花費(fèi)更多的時(shí)間建立連接。
26.三次握手中每一次沒(méi)收到報(bào)文會(huì)發(fā)生什么情況?
第一次握手服務(wù)端未收到 SYN 報(bào)文
服務(wù)端不會(huì)進(jìn)行任何的動(dòng)作,而客戶端由于一段時(shí)間內(nèi)沒(méi)有收到服務(wù)端發(fā)來(lái)的確認(rèn)報(bào)文,等待一段時(shí)間后會(huì)重新發(fā)送 SYN 報(bào)文,如果仍然沒(méi)有回應(yīng),會(huì)重復(fù)這個(gè)過(guò)程,直到發(fā)送次數(shù)超過(guò)最大重傳次數(shù)限制,就會(huì)返回連接建立失敗。
第二次握手客戶端未收到服務(wù)端響應(yīng)的 ACK 報(bào)文
客戶端會(huì)繼續(xù)重傳,直到次數(shù)限制;而服務(wù)端此時(shí)會(huì)阻塞在 accept()處,等待客戶端發(fā)送 ACK 報(bào)文
第三次握手服務(wù)端為收到客戶端發(fā)送過(guò)來(lái)的 ACK 報(bào)文
服務(wù)端同樣會(huì)采用類似客戶端的超時(shí)重傳機(jī)制,如果重試次數(shù)超過(guò)限制,則 accept()調(diào)用返回-1,服務(wù)端建立連接失敗;而此時(shí)客戶端認(rèn)為自己已經(jīng)建立連接成功,因此開(kāi)始向服務(wù)端發(fā)送數(shù)據(jù),但是服務(wù)端的 accept()系統(tǒng)調(diào)用已經(jīng)返回,此時(shí)不在監(jiān)聽(tīng)狀態(tài),因此服務(wù)端接收到客戶端發(fā)送來(lái)的數(shù)據(jù)時(shí)會(huì)發(fā)送 RST 報(bào)文給客戶端,消除客戶端單方面建立連接的狀態(tài)。
27.第二次握手傳回了 ACK,為什么還要傳回 SYN?
ACK 是為了告訴客戶端傳來(lái)的數(shù)據(jù)已經(jīng)接收無(wú)誤。
而傳回 SYN 是為了告訴客戶端,服務(wù)端響應(yīng)的確實(shí)是客戶端發(fā)送的報(bào)文。
28.第 3 次握手可以攜帶數(shù)據(jù)嗎?
第 3 次握手是可以攜帶數(shù)據(jù)的。
此時(shí)客戶端已經(jīng)處于 ESTABLISHED 狀態(tài)。對(duì)于客戶端來(lái)說(shuō),它已經(jīng)建立連接成功,并且確認(rèn)服務(wù)端的接收和發(fā)送能力是正常的。
第一次握手不能攜帶數(shù)據(jù)是出于安全的考慮,因?yàn)槿绻试S攜帶數(shù)據(jù),攻擊者每次在 SYN 報(bào)文中攜帶大量數(shù)據(jù),就會(huì)導(dǎo)致服務(wù)端消耗更多的時(shí)間和空間去處理這些報(bào)文,會(huì)造成 CPU 和內(nèi)存的消耗。
29.說(shuō)說(shuō)半連接隊(duì)列和 SYN Flood 攻擊的關(guān)系?
什么是半連接隊(duì)列?
TCP 進(jìn)入三次握手前,服務(wù)端會(huì)從 CLOSED 狀態(tài)變?yōu)?LISTEN 狀態(tài), 同時(shí)在內(nèi)部創(chuàng)建了兩個(gè)隊(duì)列:半連接隊(duì)列(SYN 隊(duì)列)和全連接隊(duì)列(ACCEPT 隊(duì)列)。

顧名思義,半連接隊(duì)列存放的是三次握手未完成的連接,全連接隊(duì)列存放的是完成三次握手的連接。
TCP 三次握手時(shí),客戶端發(fā)送 SYN 到服務(wù)端,服務(wù)端收到之后,便回復(fù) ACK 和 SYN,狀態(tài)由 LISTEN 變?yōu)?SYN_RCVD,此時(shí)這個(gè)連接就被推入了 SYN 隊(duì)列,即半連接隊(duì)列。 當(dāng)客戶端回復(fù) ACK, 服務(wù)端接收后,三次握手就完成了。這時(shí)連接會(huì)等待被具體的應(yīng)用取走,在被取走之前,它被推入 ACCEPT 隊(duì)列,即全連接隊(duì)列。
什么是 SYN Flood ?
SYN Flood 是一種典型的 DDos 攻擊,它在短時(shí)間內(nèi),偽造不存在的 IP 地址, 向服務(wù)器發(fā)送大量 SYN 報(bào)文。當(dāng)服務(wù)器回復(fù) SYN+ACK 報(bào)文后,不會(huì)收到 ACK 回應(yīng)報(bào)文,那么 SYN 隊(duì)列里的連接舊不會(huì)出對(duì)隊(duì),久?久之就會(huì)占滿服務(wù)端的 SYN 接收隊(duì)列(半連接隊(duì)列),使得服務(wù)器不能為正常?戶服務(wù)。

那有什么應(yīng)對(duì)方案呢?
主要有 syn cookie 和 SYN Proxy 防火墻等。
syn cookie:在收到 SYN 包后,服務(wù)器根據(jù)一定的方法,以數(shù)據(jù)包的源地址、端口等信息為參數(shù)計(jì)算出一個(gè) cookie 值作為自己的 SYNACK 包的序列號(hào),回復(fù) SYN+ACK 后,服務(wù)器并不立即分配資源進(jìn)行處理,等收到發(fā)送方的 ACK 包后,重新根據(jù)數(shù)據(jù)包的源地址、端口計(jì)算該包中的確認(rèn)序列號(hào)是否正確,如果正確則建立連接,否則丟棄該包。 SYN Proxy 防火墻:服務(wù)器防火墻會(huì)對(duì)收到的每一個(gè) SYN 報(bào)文進(jìn)行代理和回應(yīng),并保持半連接。等發(fā)送方將 ACK 包返回后,再重新構(gòu)造 SYN 包發(fā)到服務(wù)器,建立真正的 TCP 連接。
30.說(shuō)說(shuō) TCP 四次揮手的過(guò)程?
PS:?jiǎn)柾耆挝帐郑3R矔?huì)順道問(wèn)問(wèn)四次揮手,所以也是必須掌握知識(shí)點(diǎn)。

TCP 四次揮手過(guò)程:
數(shù)據(jù)傳輸結(jié)束之后,通信雙方都可以主動(dòng)發(fā)起斷開(kāi)連接請(qǐng)求,這里假定客戶端發(fā)起 客戶端發(fā)送釋放連接報(bào)文,第一次揮手 (FIN=1,seq=u),發(fā)送完畢后,客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)。 服務(wù)端發(fā)送確認(rèn)報(bào)文,第二次揮手 (ACK=1,ack=u+1,seq =v),發(fā)送完畢后,服務(wù)器端進(jìn)入 CLOSE_WAIT 狀態(tài),客戶端接收到這個(gè)確認(rèn)包之后,進(jìn)入 FIN_WAIT_2 狀態(tài)。 服務(wù)端發(fā)送釋放連接報(bào)文,第三次揮手 (FIN=1,ACK1,seq=w,ack=u+1),發(fā)送完畢后,服務(wù)器端進(jìn)入 LAST_ACK 狀態(tài),等待來(lái)自客戶端的最后一個(gè) ACK。 客戶端發(fā)送確認(rèn)報(bào)文,第四次揮手 (ACK=1,seq=u+1,ack=w+1),客戶端接收到來(lái)自服務(wù)器端的關(guān)閉請(qǐng)求,發(fā)送一個(gè)確認(rèn)包,并進(jìn)入 TIME_WAIT 狀態(tài),等待了某個(gè)固定時(shí)間(兩個(gè)最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒(méi)有收到服務(wù)器端的 ACK ,認(rèn)為服務(wù)器端已經(jīng)正常關(guān)閉連接,于是自己也關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)。服務(wù)器端接收到這個(gè)確認(rèn)包之后,關(guān)閉連接,進(jìn)入 CLOSED 狀態(tài)。
大白話說(shuō)四次揮手:
假如單身狗博主有一個(gè)女朋友—由于博主上班九九六,下班肝博客,導(dǎo)致沒(méi)有時(shí)間陪女朋友,女朋友忍無(wú)可忍。
女朋友:狗男人,最近你都不理我,你是不是不愛(ài)我了?你是不是外面有別的狗子了?我要和你分手? 沙雕博主一愣,怒火攻心:分手就分手,不陪你鬧了,等我把東西收拾收拾。
沙雕博主小心翼翼地裝起了自己的青軸機(jī)械鍵盤。
哼,蠢女人,我已經(jīng)收拾完了,我先滾為敬,再見(jiàn)! 女朋友:滾,滾的遠(yuǎn)遠(yuǎn)的,越遠(yuǎn)越好,我一輩子都不想再見(jiàn)到你。
揮手的故事總充滿了悲傷和遺憾!

31.TCP 揮手為什么需要四次呢?
再來(lái)回顧下四次揮手雙方發(fā) FIN 包的過(guò)程,就能理解為什么需要四次了。
關(guān)閉連接時(shí),客戶端向服務(wù)端發(fā)送 FIN時(shí),僅僅表示客戶端不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù)。服務(wù)端收到客戶端的 FIN報(bào)文時(shí),先回一個(gè)ACK應(yīng)答報(bào)文,而服務(wù)端可能還有數(shù)據(jù)需要處理和發(fā)送,等服務(wù)端不再發(fā)送數(shù)據(jù)時(shí),才發(fā)送FIN報(bào)文給客戶端來(lái)表示同意現(xiàn)在關(guān)閉連接。
從上面過(guò)程可知,服務(wù)端通常需要等待完成數(shù)據(jù)的發(fā)送和處理,所以服務(wù)端的 ACK 和 FIN 一般都會(huì)分開(kāi)發(fā)送,從而比三次握手導(dǎo)致多了一次。
32.TCP 四次揮手過(guò)程中,為什么需要等待 2MSL, 才進(jìn)入 CLOSED 關(guān)閉狀態(tài)?
為什么需要等待?
1. 為了保證客戶端發(fā)送的最后一個(gè) ACK 報(bào)文段能夠到達(dá)服務(wù)端。 這個(gè) ACK 報(bào)文段有可能丟失,因而使處在 LAST-ACK 狀態(tài)的服務(wù)端就收不到對(duì)已發(fā)送的 FIN + ACK 報(bào)文段的確認(rèn)。服務(wù)端會(huì)超時(shí)重傳這個(gè) FIN+ACK 報(bào)文段,而客戶端就能在 2MSL 時(shí)間內(nèi)(超時(shí) + 1MSL 傳輸)收到這個(gè)重傳的 FIN+ACK 報(bào)文段。接著客戶端重傳一次確認(rèn),重新啟動(dòng) 2MSL 計(jì)時(shí)器。最后,客戶端和服務(wù)器都正常進(jìn)入到 CLOSED 狀態(tài)。
2. 防止已失效的連接請(qǐng)求報(bào)文段出現(xiàn)在本連接中。客戶端在發(fā)送完最后一個(gè) ACK 報(bào)文段后,再經(jīng)過(guò)時(shí)間 2MSL,就可以使本連接持續(xù)的時(shí)間內(nèi)所產(chǎn)生的所有報(bào)文段都從網(wǎng)絡(luò)中消失。這樣就可以使下一個(gè)連接中不會(huì)出現(xiàn)這種舊的連接請(qǐng)求報(bào)文段。
為什么等待的時(shí)間是 2MSL?
MSL 是 Maximum Segment Lifetime,報(bào)?最??存時(shí)間,它是任何報(bào)?在?絡(luò)上存在的最?時(shí)間,超過(guò)這個(gè)時(shí)間報(bào)?將被丟棄。
TIME_WAIT 等待 2 倍的 MSL,?較合理的解釋是:?絡(luò)中可能存在來(lái)?發(fā)送?的數(shù)據(jù)包,當(dāng)這些發(fā)送?的數(shù)據(jù)包被接收?處理后?會(huì)向?qū)?發(fā)送響應(yīng),所以?來(lái)?回需要等待 2 倍的時(shí)間。

?如如果被動(dòng)關(guān)閉?沒(méi)有收到斷開(kāi)連接的最后的 ACK 報(bào)?,就會(huì)觸發(fā)超時(shí)重發(fā) Fin 報(bào)?,另??接收到 FIN 后,會(huì)重發(fā) ACK 給被動(dòng)關(guān)閉?, ?來(lái)?去正好 2 個(gè) MSL。
33.保活計(jì)時(shí)器有什么用?
除時(shí)間等待計(jì)時(shí)器外,TCP 還有一個(gè)保活計(jì)時(shí)器(keepalive timer)。
設(shè)想這樣的場(chǎng)景:客戶已主動(dòng)與服務(wù)器建立了 TCP 連接。但后來(lái)客戶端的主機(jī)突然發(fā)生故障。顯然,服務(wù)器以后就不能再收到客戶端發(fā)來(lái)的數(shù)據(jù)。因此,應(yīng)當(dāng)有措施使服務(wù)器不要再白白等待下去。這就需要使用保活計(jì)時(shí)器了。
服務(wù)器每收到一次客戶端的數(shù)據(jù),就重新設(shè)置保活計(jì)時(shí)器,時(shí)間的設(shè)置通常是兩個(gè)小時(shí)。若兩個(gè)小時(shí)都沒(méi)有收到客戶端的數(shù)據(jù),服務(wù)端就發(fā)送一個(gè)探測(cè)報(bào)文段,以后則每隔 75 秒鐘發(fā)送一次。若連續(xù)發(fā)送 10 個(gè)探測(cè)報(bào)文段后仍然無(wú)客戶端的響應(yīng),服務(wù)端就認(rèn)為客戶端出了故障,接著就關(guān)閉這個(gè)連接。
34.CLOSE-WAIT 和 TIME-WAIT 的狀態(tài)和意義?
CLOSE-WAIT 狀態(tài)有什么意義?
服務(wù)端收到客戶端關(guān)閉連接的請(qǐng)求并確認(rèn)之后,就會(huì)進(jìn)入 CLOSE-WAIT 狀態(tài)。此時(shí)服務(wù)端可能還有一些數(shù)據(jù)沒(méi)有傳輸完成,因此不能立即關(guān)閉連接,而 CLOSE-WAIT 狀態(tài)就是為了保證服務(wù)端在關(guān)閉連接之前將待發(fā)送的數(shù)據(jù)處理完。
TIME-WAIT 有什么意義?
TIME-WAIT 狀態(tài)發(fā)生在第四次揮手,當(dāng)客戶端向服務(wù)端發(fā)送 ACK 確認(rèn)報(bào)文后進(jìn)入 TIME-WAIT 狀態(tài)。
它存在的意義主要是兩個(gè):

防?舊連接的數(shù)據(jù)包
如果客戶端收到服務(wù)端的 FIN 報(bào)文之后立即關(guān)閉連接,但是此時(shí)服務(wù)端對(duì)應(yīng)的端口并沒(méi)有關(guān)閉,如果客戶端在相同端口建立新的連接,可能會(huì)導(dǎo)致新連接收到舊連接殘留的數(shù)據(jù)包,導(dǎo)致不可預(yù)料的異常發(fā)生。
保證連接正確關(guān)閉
假設(shè)客戶端最后一次發(fā)送的 ACK 包在傳輸?shù)臅r(shí)候丟失了,由于 TCP 協(xié)議的超時(shí)重傳機(jī)制,服務(wù)端將重發(fā) FIN 報(bào)文,如果客戶端沒(méi)有維持 TIME-WAIT 狀態(tài)而直接關(guān)閉的話,當(dāng)收到服務(wù)端重新發(fā)送的 FIN 包時(shí),客戶端就會(huì)使用 RST 包來(lái)響應(yīng)服務(wù)端,導(dǎo)致服務(wù)端以為有錯(cuò)誤發(fā)生,然而實(shí)際關(guān)閉連接過(guò)程是正常的。
35.TIME_WAIT 狀態(tài)過(guò)多會(huì)導(dǎo)致什么問(wèn)題?怎么解決?
TIME_WAIT 狀態(tài)過(guò)多會(huì)導(dǎo)致什么問(wèn)題?
如果服務(wù)器有處于 TIME-WAIT 狀態(tài)的 TCP,則說(shuō)明是由服務(wù)器?主動(dòng)發(fā)起的斷開(kāi)請(qǐng)求。
過(guò)多的 TIME-WAIT 狀態(tài)主要的危害有兩種:
第?是內(nèi)存資源占?;
第?是對(duì)端?資源的占?,?個(gè) TCP 連接?少消耗?個(gè)本地端?;
怎么解決 TIME_WAIT 狀態(tài)過(guò)多?
服務(wù)器可以設(shè)置 SO_REUSEADDR 套接字來(lái)通知內(nèi)核,如果端口被占用,但是 TCP 連接位于 TIME_WAIT 狀態(tài)時(shí)可以重用端口。 還可以使用長(zhǎng)連接的方式來(lái)減少 TCP 的連接和斷開(kāi),在長(zhǎng)連接的業(yè)務(wù)里往往不需要考慮 TIME_WAIT 狀態(tài)。
36.說(shuō)說(shuō) TCP 報(bào)文首部的格式?
看一下 TCP 報(bào)文首部的格式:

16 位端口號(hào):源端口號(hào),主機(jī)該報(bào)文段是來(lái)自哪里;目標(biāo)端口號(hào),要傳給哪個(gè)上層協(xié)議或應(yīng)用程序 32 位序號(hào):一次 TCP 通信(從 TCP 連接建立到斷開(kāi))過(guò)程中某一個(gè)傳輸方向上的字節(jié)流的每個(gè)字節(jié)的編號(hào)。 32 位確認(rèn)號(hào):用作對(duì)另一方發(fā)送的 tcp 報(bào)文段的響應(yīng)。其值是收到的 TCP 報(bào)文段的序號(hào)值加 1。 4 位首部長(zhǎng)度:表示 tcp 頭部有多少個(gè) 32bit 字(4 字節(jié))。因?yàn)?4 位最大能標(biāo)識(shí) 15,所以 TCP 頭部最長(zhǎng)是 60 字節(jié)。 6 位標(biāo)志位:URG(緊急指針是否有效),ACk(表示確認(rèn)號(hào)是否有效),PST(緩沖區(qū)尚未填滿),RST(表示要求對(duì)方重新建立連接),SYN(建立連接消息標(biāo)志接),F(xiàn)IN(表示告知對(duì)方本端要關(guān)閉連接了) 16 位窗口大小:是 TCP 流量控制的一個(gè)手段。這里說(shuō)的窗口,指的是接收通告窗口。它告訴對(duì)方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù),這樣對(duì)方就可以控制發(fā)送數(shù)據(jù)的速度。 16 位校驗(yàn)和:由發(fā)送端填充,接收端對(duì) TCP 報(bào)文段執(zhí)行 CRC 算法以檢驗(yàn) TCP 報(bào)文段在傳輸過(guò)程中是否損壞。注意,這個(gè)校驗(yàn)不僅包括 TCP 頭部,也包括數(shù)據(jù)部分。這也是 TCP 可靠傳輸?shù)囊粋€(gè)重要保障。 16 位緊急指針:一個(gè)正的偏移量。它和序號(hào)字段的值相加表示最后一個(gè)緊急數(shù)據(jù)的下一字節(jié)的序號(hào)。因此,確切地說(shuō),這個(gè)字段是緊急指針相對(duì)當(dāng)前序號(hào)的偏移,不妨稱之為緊急偏移。TCP 的緊急指針是發(fā)送端向接收端發(fā)送緊急數(shù)據(jù)的方法。
37.TCP 是如何保證可靠性的?
TCP 主要提供了檢驗(yàn)和、序列號(hào)/確認(rèn)應(yīng)答、超時(shí)重傳、最大消息長(zhǎng)度、滑動(dòng)窗口控制等方法實(shí)現(xiàn)了可靠性傳輸。

連接管理:TCP 使用三次握手和四次揮手保證可靠地建立連接和釋放連接,這里就不用多說(shuō)了。 校驗(yàn)和:TCP 將保持它首部和數(shù)據(jù)的檢驗(yàn)和。這是一個(gè)端到端的檢驗(yàn)和,目的是檢測(cè)數(shù)據(jù)在傳輸過(guò)程中的任何變化。如果接收端的檢驗(yàn)和有差錯(cuò),TCP 將丟棄這個(gè)報(bào)文段和不確認(rèn)收到此報(bào)文段。

TCP 校驗(yàn)和
序列號(hào)/確認(rèn)應(yīng)答:TCP 給發(fā)送的每一個(gè)包進(jìn)行編號(hào),接收方會(huì)對(duì)收到的包進(jìn)行應(yīng)答,發(fā)送方就會(huì)知道接收方是否收到對(duì)應(yīng)的包,如果發(fā)現(xiàn)沒(méi)有收到,就會(huì)重發(fā),這樣就能保證數(shù)據(jù)的完整性。就像老師上課,會(huì)問(wèn)一句,這一章聽(tīng)懂了嗎?沒(méi)聽(tīng)懂再講一遍。

**流量控制:**TCP 連接的每一方都有固定大小的緩沖空間,TCP 的接收端只允許發(fā)送端發(fā)送接收端緩沖區(qū)能接納的數(shù)據(jù)。當(dāng)接收方來(lái)不及處理發(fā)送方的數(shù)據(jù),能提示發(fā)送方降低發(fā)送的速率,防止包丟失。TCP 使用的流量控制協(xié)議是可變大小的滑動(dòng)窗口協(xié)議。(TCP 利用滑動(dòng)窗口實(shí)現(xiàn)流量控制)

最大消息長(zhǎng)度:在建立 TCP 連接的時(shí)候,雙方約定一個(gè)最大的長(zhǎng)度(MSS)作為發(fā)送的單位,重傳的時(shí)候也是以這個(gè)單位來(lái)進(jìn)行重傳。理想的情況下是該長(zhǎng)度的數(shù)據(jù)剛好不被網(wǎng)絡(luò)層分塊。

**超時(shí)重傳:**超時(shí)重傳是指發(fā)送出去的數(shù)據(jù)包到接收到確認(rèn)包之間的時(shí)間,如果超過(guò)了這個(gè)時(shí)間會(huì)被認(rèn)為是丟包了,需要重傳。

**擁塞控制:**如果網(wǎng)絡(luò)非常擁堵,此時(shí)再發(fā)送數(shù)據(jù)就會(huì)加重網(wǎng)絡(luò)負(fù)擔(dān),那么發(fā)送的數(shù)據(jù)段很可能超過(guò)了最大生存時(shí)間也沒(méi)有到達(dá)接收方,就會(huì)產(chǎn)生丟包問(wèn)題。為此 TCP 引入慢啟動(dòng)機(jī)制,先發(fā)出少量數(shù)據(jù),就像探路一樣,先摸清當(dāng)前的網(wǎng)絡(luò)擁堵?tīng)顟B(tài)后,再?zèng)Q定按照多大的速度傳送數(shù)據(jù)。

38.說(shuō)說(shuō) TCP 的流量控制?
TCP 提供了一種機(jī)制,可以讓發(fā)送端根據(jù)接收端的實(shí)際接收能力控制發(fā)送的數(shù)據(jù)量,這就是流量控制。
TCP 通過(guò)滑動(dòng)窗口來(lái)控制流量,我們看下簡(jiǎn)要流程:
首先雙方三次握手,初始化各自的窗口大小,均為 400 個(gè)字節(jié)。

假如當(dāng)前發(fā)送方給接收方發(fā)送了 200 個(gè)字節(jié),那么,發(fā)送方的 SND.NXT會(huì)右移 200 個(gè)字節(jié),也就是說(shuō)當(dāng)前的可用窗口減少了 200 個(gè)字節(jié)。接受方收到后,放到緩沖隊(duì)列里面,REV.WND =400-200=200 字節(jié),所以 win=200 字節(jié)返回給發(fā)送方。接收方會(huì)在 ACK 的報(bào)文首部帶上縮小后的滑動(dòng)窗口 200 字節(jié) 發(fā)送方又發(fā)送 200 字節(jié)過(guò)來(lái),200 字節(jié)到達(dá),繼續(xù)放到緩沖隊(duì)列。不過(guò)這時(shí)候,由于大量負(fù)載的原因,接受方處理不了這么多字節(jié),只能處理 100 字節(jié),剩余的 100 字節(jié)繼續(xù)放到緩沖隊(duì)列。這時(shí)候,REV.WND = 400-200-100=100 字節(jié),即 win=100 返回發(fā)送方。 發(fā)送方繼續(xù)發(fā)送 100 字節(jié)過(guò)來(lái),這時(shí)候,接收窗口 win 變?yōu)?0。 發(fā)送方停止發(fā)送,開(kāi)啟一個(gè)定時(shí)任務(wù),每隔一段時(shí)間,就去詢問(wèn)接受方,直到 win 大于 0,才繼續(xù)開(kāi)始發(fā)送。
39.詳細(xì)說(shuō)說(shuō) TCP 的滑動(dòng)窗口?
TCP 發(fā)送一個(gè)數(shù)據(jù),如果需要收到確認(rèn)應(yīng)答,才會(huì)發(fā)送下一個(gè)數(shù)據(jù)。這樣的話就會(huì)有個(gè)缺點(diǎn):效率會(huì)比較低。
“用一個(gè)比喻,我們?cè)谖⑿派狭奶欤愦蛲暌痪湓挘一貜?fù)一句之后,你才能打下一句。假如我沒(méi)有及時(shí)回復(fù)呢?你是把話憋著不說(shuō)嗎?然后傻傻等到我回復(fù)之后再接著發(fā)下一句?”
為了解決這個(gè)問(wèn)題,TCP 引入了窗口,它是操作系統(tǒng)開(kāi)辟的一個(gè)緩存空間。窗口大小值表示無(wú)需等待確認(rèn)應(yīng)答,而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值。
TCP 頭部有個(gè)字段叫 win,也即那個(gè) 16 位的窗口大小,它告訴對(duì)方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù),這樣對(duì)方就可以控制發(fā)送數(shù)據(jù)的速度,從而達(dá)到流量控制的目的。
“通俗點(diǎn)講,就是接受方每次收到數(shù)據(jù)包,在發(fā)送確認(rèn)報(bào)文的時(shí)候,同時(shí)告訴發(fā)送方,自己的緩存區(qū)還有多少空余空間,緩沖區(qū)的空余空間,我們就稱之為接受窗口大小。這就是 win。”
TCP 滑動(dòng)窗口分為兩種: 發(fā)送窗口和接收窗口。發(fā)送端的滑動(dòng)窗口包含四大部分,如下:
已發(fā)送且已收到 ACK 確認(rèn) 已發(fā)送但未收到 ACK 確認(rèn) 未發(fā)送但可以發(fā)送 未發(fā)送也不可以發(fā)送

深藍(lán)色框里就是發(fā)送窗口。 SND.WND: 表示發(fā)送窗口的大小, 上圖虛線框的格子數(shù)是 10 個(gè),即發(fā)送窗口大小是 10。 SND.NXT:下一個(gè)發(fā)送的位置,它指向未發(fā)送但可以發(fā)送的第一個(gè)字節(jié)的序列號(hào)。 SND.UNA: 一個(gè)絕對(duì)指針,它指向的是已發(fā)送但未確認(rèn)的第一個(gè)字節(jié)的序列號(hào)。
接收方的滑動(dòng)窗口包含三大部分,如下:
已成功接收并確認(rèn) 未收到數(shù)據(jù)但可以接收 未收到數(shù)據(jù)并不可以接收的數(shù)據(jù)

藍(lán)色框內(nèi),就是接收窗口。 REV.WND: 表示接收窗口的大小, 上圖虛線框的格子就是 9 個(gè)。 REV.NXT: 下一個(gè)接收的位置,它指向未收到但可以接收的第一個(gè)字節(jié)的序列號(hào)。
40.了解 Nagle 算法和延遲確認(rèn)嗎?
Nagle 算法和延遲確認(rèn)是干什么的?
當(dāng)我們 TCP 報(bào)?的承載的數(shù)據(jù)?常?的時(shí)候,例如?個(gè)字節(jié),那么整個(gè)?絡(luò)的效率是很低的,因?yàn)槊總€(gè) TCP 報(bào)?中都會(huì)有 20 個(gè)字節(jié)的 TCP 頭部,也會(huì)有 20 個(gè)字節(jié)的 IP 頭部,?數(shù)據(jù)只有?個(gè)字節(jié),所以在整個(gè)報(bào)?中有效數(shù)據(jù)占有的比例就會(huì)?常低。

這就好像快遞員開(kāi)著?貨?送?個(gè)?包裹?樣浪費(fèi)。
那么就出現(xiàn)了常?的兩種策略,來(lái)減少?報(bào)?的傳輸,分別是:
Nagle 算法 延遲確認(rèn)
Nagle 算法
Nagle 算法:任意時(shí)刻,最多只能有一個(gè)未被確認(rèn)的小段。所謂 “小段”,指的是小于 MSS 尺寸的數(shù)據(jù)塊,所謂 “未被確認(rèn)”,是指一個(gè)數(shù)據(jù)塊發(fā)送出去后,沒(méi)有收到對(duì)方發(fā)送的 ACK 確認(rèn)該數(shù)據(jù)已收到。
Nagle 算法的策略:
沒(méi)有已發(fā)送未確認(rèn)報(bào)?時(shí),?刻發(fā)送數(shù)據(jù)。 存在未確認(rèn)報(bào)?時(shí),直到「沒(méi)有已發(fā)送未確認(rèn)報(bào)?」或「數(shù)據(jù)?度達(dá)到 MSS ??」時(shí),再發(fā)送數(shù)據(jù)。
只要沒(méi)滿?上?條件中的?條,發(fā)送??直在囤積數(shù)據(jù),直到滿?上?的發(fā)送條件。
延遲確認(rèn)
事實(shí)上當(dāng)沒(méi)有攜帶數(shù)據(jù)的 ACK,它的?絡(luò)效率也是很低的,因?yàn)樗灿?40 個(gè)字節(jié)的 IP 頭 和 TCP 頭,但卻沒(méi)有攜帶數(shù)據(jù)報(bào)?。
為了解決 ACK 傳輸效率低問(wèn)題,所以就衍?出了 TCP 延遲確認(rèn)。
TCP 延遲確認(rèn)的策略:
當(dāng)有響應(yīng)數(shù)據(jù)要發(fā)送時(shí),ACK 會(huì)隨著響應(yīng)數(shù)據(jù)?起?刻發(fā)送給對(duì)? 當(dāng)沒(méi)有響應(yīng)數(shù)據(jù)要發(fā)送時(shí),ACK 將會(huì)延遲?段時(shí)間,以等待是否有響應(yīng)數(shù)據(jù)可以?起發(fā)送 如果在延遲等待發(fā)送 ACK 期間,對(duì)?的第?個(gè)數(shù)據(jù)報(bào)??到達(dá)了,這時(shí)就會(huì)?刻發(fā)送 ACK
一般情況下,Nagle 算法和延遲確認(rèn)不能一起使用,Nagle 算法意味著延遲發(fā),延遲確認(rèn)意味著延遲接收,兩個(gè)湊在一起就會(huì)造成更大的延遲,會(huì)產(chǎn)生性能問(wèn)題。
41.說(shuō)說(shuō) TCP 的擁塞控制?
什么是擁塞控制?不是有了流量控制嗎?
前?的流量控制是避免發(fā)送?的數(shù)據(jù)填滿接收?的緩存,但是并不知道整個(gè)?絡(luò)之中發(fā)?了什么。
?般來(lái)說(shuō),計(jì)算機(jī)?絡(luò)都處在?個(gè)共享的環(huán)境。因此也有可能會(huì)因?yàn)槠渌鳈C(jī)之間的通信使得?絡(luò)擁堵。
在?絡(luò)出現(xiàn)擁堵時(shí),如果繼續(xù)發(fā)送?量數(shù)據(jù)包,可能會(huì)導(dǎo)致數(shù)據(jù)包時(shí)延、丟失等,這時(shí) TCP 就會(huì)重傳數(shù)據(jù),但是?重傳就會(huì)導(dǎo)致?絡(luò)的負(fù)擔(dān)更重,于是會(huì)導(dǎo)致更?的延遲以及更多的丟包,這個(gè)情況就會(huì)進(jìn)?惡性循環(huán)被不斷地放?....
所以,TCP 不能忽略整個(gè)網(wǎng)絡(luò)中發(fā)?的事,它被設(shè)計(jì)成?個(gè)?私的協(xié)議,當(dāng)?絡(luò)發(fā)送擁塞時(shí),TCP 會(huì)?我犧牲,降低發(fā)送的數(shù)據(jù)流。
于是,就有了擁塞控制,控制的?的就是避免發(fā)送?的數(shù)據(jù)填滿整個(gè)?絡(luò)。
就像是一個(gè)水管,不能讓太多的水(數(shù)據(jù)流)流入水管,如果超過(guò)水管的承受能力,水管會(huì)被撐爆(丟包)。

發(fā)送方維護(hù)一個(gè)擁塞窗口 cwnd(congestion window) 的變量,調(diào)節(jié)所要發(fā)送數(shù)據(jù)的量。
什么是擁塞窗??和發(fā)送窗?有什么關(guān)系呢?
擁塞窗? cwnd是發(fā)送?維護(hù)的?個(gè)的狀態(tài)變量,它會(huì)根據(jù)?絡(luò)的擁塞程度動(dòng)態(tài)變化的。
發(fā)送窗? swnd 和接收窗? rwnd 是約等于的關(guān)系,那么由于加?了擁塞窗?的概念后,此時(shí)發(fā)送窗?的值是 swnd = min(cwnd, rwnd),也就是擁塞窗?和接收窗?中的最?值。
擁塞窗? cwnd 變化的規(guī)則:
只要?絡(luò)中沒(méi)有出現(xiàn)擁塞, cwnd 就會(huì)增?; 但?絡(luò)中出現(xiàn)了擁塞, cwnd 就減少;
擁塞控制有哪些常用算法?
擁塞控制主要有這幾種常用算法:

慢啟動(dòng) 擁塞避免 擁塞發(fā)生 快速恢復(fù)
慢啟動(dòng)算法
慢啟動(dòng)算法,慢慢啟動(dòng)。
它表示 TCP 建立連接完成后,一開(kāi)始不要發(fā)送大量的數(shù)據(jù),而是先探測(cè)一下網(wǎng)絡(luò)的擁塞程度。由小到大逐漸增加擁塞窗口的大小,如果沒(méi)有出現(xiàn)丟包,每收到一個(gè) ACK,就將擁塞窗口 cwnd 大小就加 1(單位是 MSS)。每輪次發(fā)送窗口增加一倍,呈指數(shù)增長(zhǎng),如果出現(xiàn)丟包,擁塞窗口就減半,進(jìn)入擁塞避免階段。
舉個(gè)例子:
連接建?完成后,?開(kāi)始初始化 cwnd = 1 ,表示可以傳?個(gè) MSS ??的數(shù)據(jù)。 當(dāng)收到?個(gè) ACK 確認(rèn)應(yīng)答后,cwnd 增加 1,于是?次能夠發(fā)送 2 個(gè) 當(dāng)收到 2 個(gè)的 ACK 確認(rèn)應(yīng)答后, cwnd 增加 2,于是就可以?之前多發(fā) 2 個(gè),所以這?次能夠發(fā)送 4 個(gè) 當(dāng)這 4 個(gè)的 ACK 確認(rèn)到來(lái)的時(shí)候,每個(gè)確認(rèn) cwnd 增加 1, 4 個(gè)確認(rèn) cwnd 增加 4,于是就可以?之前多發(fā) 4 個(gè),所以這?次能夠發(fā)送 8 個(gè)。

發(fā)包的個(gè)數(shù)是指數(shù)性的增?。

為了防止 cwnd 增長(zhǎng)過(guò)大引起網(wǎng)絡(luò)擁塞,還需設(shè)置一個(gè)慢啟動(dòng)閥值 ssthresh(slow start threshold)狀態(tài)變量。當(dāng)cwnd到達(dá)該閥值后,就好像水管被關(guān)小了水龍頭一樣,減少擁塞狀態(tài)。即當(dāng) cwnd >ssthresh 時(shí),進(jìn)入了擁塞避免算法。
擁塞避免算法
一般來(lái)說(shuō),慢啟動(dòng)閥值 ssthresh 是 65535 字節(jié),cwnd到達(dá)慢啟動(dòng)閥值后
每收到一個(gè) ACK 時(shí),cwnd = cwnd + 1/cwnd 當(dāng)每過(guò)一個(gè) RTT 時(shí),cwnd = cwnd + 1
顯然這是一個(gè)線性上升的算法,避免過(guò)快導(dǎo)致網(wǎng)絡(luò)擁塞問(wèn)題。
接著上面慢啟動(dòng)的例子,假定 ssthresh 為 8 ::
當(dāng) 8 個(gè) ACK 應(yīng)答確認(rèn)到來(lái)時(shí),每個(gè)確認(rèn)增加 1/8,8 個(gè) ACK 確認(rèn) cwnd ?共增加 1,于是這?次能夠發(fā)送 9 個(gè) MSS ??的數(shù)據(jù),變成了線性增?。

擁塞發(fā)生
當(dāng)網(wǎng)絡(luò)擁塞發(fā)生丟包時(shí),會(huì)有兩種情況:
RTO 超時(shí)重傳 快速重傳
如果是發(fā)生了 RTO 超時(shí)重傳,就會(huì)使用擁塞發(fā)生算法
慢啟動(dòng)閥值 sshthresh = cwnd /2 cwnd 重置為 1 進(jìn)入新的慢啟動(dòng)過(guò)程

這種方式就像是飆車的時(shí)候急剎車,還飛速倒車,這。。。
其實(shí)還有更好的處理方式,就是快速重傳。發(fā)送方收到 3 個(gè)連續(xù)重復(fù)的 ACK 時(shí),就會(huì)快速地重傳,不必等待 RTO 超時(shí)再重傳。
發(fā)?快速重傳的擁塞發(fā)?算法:
擁塞窗口大小 cwnd = cwnd/2 慢啟動(dòng)閥值 ssthresh = cwnd 進(jìn)入快速恢復(fù)算法
快速恢復(fù)
快速重傳和快速恢復(fù)算法一般同時(shí)使用。快速恢復(fù)算法認(rèn)為,還有 3 個(gè)重復(fù) ACK 收到,說(shuō)明網(wǎng)絡(luò)也沒(méi)那么糟糕,所以沒(méi)有必要像 RTO 超時(shí)那么強(qiáng)烈。
正如前面所說(shuō),進(jìn)入快速恢復(fù)之前,cwnd 和 sshthresh 已被更新:
cwnd = cwnd /2
- sshthresh = cwnd
然后,進(jìn)?快速恢復(fù)算法如下:
cwnd = sshthresh + 3 重傳重復(fù)的那幾個(gè) ACK(即丟失的那幾個(gè)數(shù)據(jù)包) 如果再收到重復(fù)的 ACK,那么 cwnd = cwnd +1 如果收到新數(shù)據(jù)的 ACK 后, cwnd = sshthresh。因?yàn)槭盏叫聰?shù)據(jù)的 ACK,表明恢復(fù)過(guò)程已經(jīng)結(jié)束,可以再次進(jìn)入了擁塞避免的算法了。

42.說(shuō)說(shuō) TCP 的重傳機(jī)制?
重傳包括超時(shí)重傳、快速重傳、帶選擇確認(rèn)的重傳(SACK)、重復(fù) SACK 四種。

超時(shí)重傳
超時(shí)重傳,是 TCP 協(xié)議保證數(shù)據(jù)可靠性的另一個(gè)重要機(jī)制,其原理是在發(fā)送某一個(gè)數(shù)據(jù)以后就開(kāi)啟一個(gè)計(jì)時(shí)器,在一定時(shí)間內(nèi)如果沒(méi)有得到發(fā)送的數(shù)據(jù)報(bào)的 ACK 報(bào)文,那么就重新發(fā)送數(shù)據(jù),直到發(fā)送成功為止。
超時(shí)時(shí)間應(yīng)該設(shè)置為多少呢?
先來(lái)看下什么叫 RTT(Round-Trip Time,往返時(shí)間)。

RTT 就是數(shù)據(jù)完全發(fā)送完,到收到確認(rèn)信號(hào)的時(shí)間,即數(shù)據(jù)包的一次往返時(shí)間。
超時(shí)重傳時(shí)間,就是 RTO(Retransmission Timeout)。那么,RTO 到底設(shè)置多大呢?
如果 RTO 設(shè)置很大,等了很久都沒(méi)重發(fā),這樣肯定就不行。 如果 RTO 設(shè)置很小,那很可能數(shù)據(jù)都沒(méi)有丟失,就開(kāi)始重發(fā)了,這會(huì)導(dǎo)致網(wǎng)絡(luò)阻塞,從而惡性循環(huán),導(dǎo)致更多的超時(shí)出現(xiàn)。
一般來(lái)說(shuō),RTO 略微大于 RTT,效果是最佳的。
其實(shí),RTO 有個(gè)標(biāo)準(zhǔn)方法的計(jì)算公式,也叫 Jacobson / Karels 算法。
首先計(jì)算 SRTT(即計(jì)算平滑的 RTT)
SRTT = (1 - α) * SRTT + α * RTT //求 SRTT 的加權(quán)平均
其次,計(jì)算 RTTVAR (round-trip time variation)
RTTVAR = (1 - β) * RTTVAR + β * (|RTT - SRTT|) //計(jì)算 SRTT 與真實(shí)值的差距
最后,得出最終的 RTO
RTO = μ * SRTT + ? * RTTVAR = SRTT + 4·RTTVAR
在 Linux 下,α = 0.125,β = 0.25, μ = 1,? = 4。別問(wèn)這些參數(shù)是怎么來(lái)的,它們是大量實(shí)踐,調(diào)出的最優(yōu)參數(shù)。
超時(shí)重傳不是十分完美的重傳方案,它有這些缺點(diǎn):
當(dāng)一個(gè)報(bào)文丟失時(shí),會(huì)等待一定的超時(shí)周期,才重傳分組,增加了端到端的時(shí)延。 當(dāng)一個(gè)報(bào)文丟失時(shí),在其等待超時(shí)的過(guò)程中,可能會(huì)出現(xiàn)這種情況:其后的報(bào)文段已經(jīng)被接收端接收但卻遲遲得不到確認(rèn),發(fā)送端會(huì)認(rèn)為也丟失了,從而引起不必要的重傳,既浪費(fèi)資源也浪費(fèi)時(shí)間。
并且,對(duì)于 TCP,如果發(fā)生一次超時(shí)重傳,時(shí)間間隔下次就會(huì)加倍。
快速重傳
TCP 還有另外?種快速重傳(Fast Retransmit)機(jī)制,它不以時(shí)間為驅(qū)動(dòng),?是以數(shù)據(jù)驅(qū)動(dòng)重傳。
它不以時(shí)間驅(qū)動(dòng),而是以數(shù)據(jù)驅(qū)動(dòng)。它是基于接收端的反饋信息來(lái)引發(fā)重傳的。
可以用它來(lái)解決超時(shí)重發(fā)的時(shí)間等待問(wèn)題,快速重傳流程如下:

在上圖,發(fā)送?發(fā)出了 1,2,3,4,5 份數(shù)據(jù):
第?份 Seq1 先送到了,于是就 Ack 回 2; 結(jié)果 Seq2 因?yàn)槟承┰驔](méi)收到,Seq3 到達(dá)了,于是還是 Ack 回 2; 后?的 Seq4 和 Seq5 都到了,但還是 Ack 回 2,因?yàn)?Seq2 還是沒(méi)有收到; 發(fā)送端收到了三個(gè) Ack = 2 的確認(rèn),知道了 Seq2 還沒(méi)有收到,就會(huì)在定時(shí)器過(guò)期之前,重傳丟失的 Seq2。 最后,收到了 Seq2,此時(shí)因?yàn)?Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。
快速重傳機(jī)制只解決了?個(gè)問(wèn)題,就是超時(shí)時(shí)間的問(wèn)題,但是它依然?臨著另外?個(gè)問(wèn)題。就是重傳的時(shí)候,是重傳之前的?個(gè),還是重傳所有的問(wèn)題。
?如對(duì)于上?的例?,是重傳 Seq2 呢?還是重傳 Seq2、Seq3、Seq4、Seq5 呢?因?yàn)榘l(fā)送端并不清楚這連續(xù)的三個(gè) Ack 2 是誰(shuí)傳回來(lái)的。
根據(jù) TCP 不同的實(shí)現(xiàn),以上兩種情況都是有可能的。可?,這是?把雙刃劍。
為了解決不知道該重傳哪些 TCP 報(bào)?,于是就有 SACK ?法。
帶選擇確認(rèn)的重傳(SACK)
為了解決應(yīng)該重傳多少個(gè)包的問(wèn)題? TCP 提供了帶選擇確認(rèn)的重傳(即 SACK,Selective Acknowledgment)。
SACK 機(jī)制就是,在快速重傳的基礎(chǔ)上,接收方返回最近收到報(bào)文段的序列號(hào)范圍,這樣發(fā)送方就知道接收方哪些數(shù)據(jù)包是沒(méi)收到的。這樣就很清楚應(yīng)該重傳哪些數(shù)據(jù)包。

如上圖中,發(fā)送?收到了三次同樣的 ACK 確認(rèn)報(bào)?,于是就會(huì)觸發(fā)快速重發(fā)機(jī)制,通過(guò) SACK 信息發(fā)現(xiàn)只有 200~299 這段數(shù)據(jù)丟失,則重發(fā)時(shí),就只選擇了這個(gè) TCP 段進(jìn)?重發(fā)。
重復(fù) SACK(D-SACK)
D-SACK,英文是 Duplicate SACK,是在 SACK 的基礎(chǔ)上做了一些擴(kuò)展,主要用來(lái)告訴發(fā)送方,有哪些數(shù)據(jù)包,自己重復(fù)接受了。
DSACK 的目的是幫助發(fā)送方判斷,是否發(fā)生了包失序、ACK 丟失、包重復(fù)或偽重傳。讓 TCP 可以更好的做網(wǎng)絡(luò)流控。
例如 ACK 丟包導(dǎo)致的數(shù)據(jù)包重復(fù):

接收?發(fā)給發(fā)送?的兩個(gè) ACK 確認(rèn)應(yīng)答都丟失了,所以發(fā)送?超時(shí)后,重傳第?個(gè)數(shù)據(jù)包(3000 ~
3499)
于是接收?發(fā)現(xiàn)數(shù)據(jù)是重復(fù)收到的,于是回了?個(gè) SACK = 3000~3500,告訴「發(fā)送?」 3000~3500 的數(shù)據(jù)早已被接收了,因?yàn)?ACK 都到了 4000 了,已經(jīng)意味著 4000 之前的所有數(shù)據(jù)都已收到,所以這個(gè) SACK 就代表著 D-SACK 。這樣發(fā)送?就知道了,數(shù)據(jù)沒(méi)有丟,是接收?的 ACK 確認(rèn)報(bào)?丟了。
43.說(shuō)說(shuō) TCP 的粘包和拆包?
TCP 的粘包和拆包更多的是業(yè)務(wù)上的概念!
什么是 TCP 粘包和拆包?
TCP 是面向流,沒(méi)有界限的一串?dāng)?shù)據(jù)。TCP 底層并不了解上層業(yè)務(wù)數(shù)據(jù)的具體含義,它會(huì)根據(jù) TCP 緩沖區(qū)的實(shí)際情況進(jìn)行包的劃分,所以在業(yè)務(wù)上認(rèn)為,一個(gè)完整的包可能會(huì)被 TCP 拆分成多個(gè)包進(jìn)行發(fā)送,也有可能把多個(gè)小的包封裝成一個(gè)大的數(shù)據(jù)包發(fā)送,這就是所謂的 TCP 粘包和拆包問(wèn)題。

為什么會(huì)產(chǎn)生粘包和拆包呢?
要發(fā)送的數(shù)據(jù)小于 TCP 發(fā)送緩沖區(qū)的大小,TCP 將多次寫(xiě)入緩沖區(qū)的數(shù)據(jù)一次發(fā)送出去,將會(huì)發(fā)生粘包; 接收數(shù)據(jù)端的應(yīng)用層沒(méi)有及時(shí)讀取接收緩沖區(qū)中的數(shù)據(jù),將發(fā)生粘包; 要發(fā)送的數(shù)據(jù)大于 TCP 發(fā)送緩沖區(qū)剩余空間大小,將會(huì)發(fā)生拆包; 待發(fā)送數(shù)據(jù)大于 MSS(最大報(bào)文長(zhǎng)度),TCP 在傳輸前將進(jìn)行拆包。即 TCP 報(bào)文長(zhǎng)度 - TCP 頭部長(zhǎng)度 > MSS。
那怎么解決呢?
發(fā)送端將每個(gè)數(shù)據(jù)包封裝為固定長(zhǎng)度 在數(shù)據(jù)尾部增加特殊字符進(jìn)行分割 將數(shù)據(jù)分為兩部分,一部分是頭部,一部分是內(nèi)容體;其中頭部結(jié)構(gòu)大小固定,且有一個(gè)字段聲明內(nèi)容體的大小。
UDP
UDP 問(wèn)的不多,基本上是被拿來(lái)和 TCP 比較。
44.說(shuō)說(shuō) TCP 和 UDP 的區(qū)別?
最根本區(qū)別:TCP 是面向連接,而 UDP 是無(wú)連接。

可以這么形容:TCP 是打電話,UDP 是大喇叭。

說(shuō)說(shuō) TCP 和 UDP 的應(yīng)用場(chǎng)景?
TCP 應(yīng)用場(chǎng)景: 效率要求相對(duì)低,但對(duì)準(zhǔn)確性要求相對(duì)高的場(chǎng)景。因?yàn)閭鬏斨行枰獙?duì)數(shù)據(jù)確認(rèn)、重發(fā)、排序等操作,相比之下效率沒(méi)有 UDP 高。例如:文件傳輸(準(zhǔn)確高要求高、但是速度可以相對(duì)慢)、收發(fā)郵件、遠(yuǎn)程登錄。 UDP 應(yīng)用場(chǎng)景: 效率要求相對(duì)高,對(duì)準(zhǔn)確性要求相對(duì)低的場(chǎng)景。例如:QQ 聊天、在線視頻、網(wǎng)絡(luò)語(yǔ)音電話(即時(shí)通訊,速度要求高,但是出現(xiàn)偶爾斷續(xù)不是太大問(wèn)題,并且此處完全不可以使用重發(fā)機(jī)制)、廣播通信(廣播、多播)。
45.為什么 QQ 采用 UDP 協(xié)議?
PS:這是多年前的老題了,拉出來(lái)懷懷舊。

首先,QQ 并不是完全基于 UDP 實(shí)現(xiàn)。比如在使用 QQ 進(jìn)行文件傳輸?shù)然顒?dòng)的時(shí)候,就會(huì)使用 TCP 作為可靠傳輸?shù)谋WC。 使用 UDP 進(jìn)行交互通信的好處在于,延遲較短,對(duì)數(shù)據(jù)丟失的處理比較簡(jiǎn)單。同時(shí),TCP 是一個(gè)全雙工協(xié)議,需要建立連接,所以網(wǎng)絡(luò)開(kāi)銷也會(huì)相對(duì)大。 如果使用 QQ 語(yǔ)音和 QQ 視頻的話,UDP 的優(yōu)勢(shì)就更為突出了,首先延遲較小。最重要的一點(diǎn)是不可靠傳輸,這意味著如果數(shù)據(jù)丟失的話,不會(huì)有重傳。因?yàn)橛脩粢话銇?lái)說(shuō)可以接受圖像稍微模糊一點(diǎn),聲音稍微不清晰一點(diǎn),但是如果在幾秒鐘以后再出現(xiàn)之前丟失的畫(huà)面和聲音,這恐怕是很難接受的。 由于 QQ 的服務(wù)器設(shè)計(jì)容量是海量級(jí)的應(yīng)用,一臺(tái)服務(wù)器要同時(shí)容納十幾萬(wàn)的并發(fā)連接,因此服務(wù)器端只有采用 UDP 協(xié)議與客戶端進(jìn)行通訊才能保證這種超大規(guī)模的服務(wù)
簡(jiǎn)單總結(jié)一下:UDP 協(xié)議是無(wú)連接方式的協(xié)議,它的效率高,速度快,占資源少,對(duì)服務(wù)器的壓力比較小。但是其傳輸機(jī)制為不可靠傳送,必須依靠輔助的算法來(lái)完成傳輸控制。QQ 采用的通信協(xié)議以 UDP 為主,輔以 TCP 協(xié)議。
46.UDP 協(xié)議為什么不可靠?
UDP 在傳輸數(shù)據(jù)之前不需要先建立連接,遠(yuǎn)地主機(jī)的運(yùn)輸層在接收到 UDP 報(bào)文后,不需要確認(rèn),提供不可靠交付。總結(jié)就以下四點(diǎn):
不保證消息交付:不確認(rèn),不重傳,無(wú)超時(shí) 不保證交付順序:不設(shè)置包序號(hào),不重排,不會(huì)發(fā)生隊(duì)首阻塞 不跟蹤連接狀態(tài):不必建立連接或重啟狀態(tài)機(jī) 不進(jìn)行擁塞控制:不內(nèi)置客戶端或網(wǎng)絡(luò)反饋機(jī)制
47.DNS 為什么要用 UDP?
更準(zhǔn)確地說(shuō),DNS 既使用 TCP 又使用 UDP。
當(dāng)進(jìn)行區(qū)域傳送(主域名服務(wù)器向輔助域名服務(wù)器傳送變化的那部分?jǐn)?shù)據(jù))時(shí)會(huì)使用 TCP,因?yàn)閿?shù)據(jù)同步傳送的數(shù)據(jù)量比一個(gè)請(qǐng)求和應(yīng)答的數(shù)據(jù)量要多,而 TCP 允許的報(bào)文長(zhǎng)度更長(zhǎng),因此為了保證數(shù)據(jù)的正確性,會(huì)使用基于可靠連接的 TCP。
當(dāng)客戶端想 DNS 服務(wù)器查詢域名(域名解析)的時(shí)候,一般返回的內(nèi)容不會(huì)超過(guò) UDP 報(bào)文的最大長(zhǎng)度,即 512 字節(jié),用 UDP 傳輸時(shí),不需要?jiǎng)?chuàng)建連接,從而大大提高了響應(yīng)速度,但這要求域名解析服務(wù)器和域名服務(wù)器都必須自己處理超時(shí)和重傳從而保證可靠性。
IP
48.IP 協(xié)議的定義和作用?
IP 協(xié)議是什么?
IP 協(xié)議(Internet Protocol)又被稱為互聯(lián)網(wǎng)協(xié)議,是支持網(wǎng)間互聯(lián)的數(shù)據(jù)包協(xié)議,工作在網(wǎng)際層,主要目的就是為了提高網(wǎng)絡(luò)的可擴(kuò)展性。
通過(guò)網(wǎng)際協(xié)議 IP,可以把參與互聯(lián)的,性能各異的網(wǎng)絡(luò)看作一個(gè)統(tǒng)一的網(wǎng)絡(luò)。

和傳輸層 TCP 相比,IP 協(xié)議是一種無(wú)連接/不可靠、盡力而為的數(shù)據(jù)包傳輸服務(wù),和 TCP 協(xié)議一起構(gòu)成了 TCP/IP 協(xié)議的核心。
IP 協(xié)議有哪些作用?
IP 協(xié)議主要有以下幾個(gè)作用:
尋址和路由:在 IP 數(shù)據(jù)報(bào)中攜帶源 IP 地址和目的 IP 地址來(lái)表示該數(shù)據(jù)包的源主機(jī)和目標(biāo)主機(jī)。IP 數(shù)據(jù)報(bào)在傳輸過(guò)程中,每個(gè)中間節(jié)點(diǎn)(IP 網(wǎng)關(guān)、路由器)只根據(jù)網(wǎng)絡(luò)地址來(lái)進(jìn)行轉(zhuǎn)發(fā),如果中間節(jié)點(diǎn)是路由器,則路由器會(huì)根據(jù)路由表選擇合適的路徑。IP 協(xié)議根據(jù)路由選擇協(xié)議提供的路由信息對(duì) IP 數(shù)據(jù)報(bào)進(jìn)行轉(zhuǎn)發(fā),直至目標(biāo)主機(jī)。 分段和重組:IP 數(shù)據(jù)報(bào)在傳輸過(guò)程中可能會(huì)經(jīng)過(guò)不同的網(wǎng)絡(luò),在不同的網(wǎng)絡(luò)中數(shù)據(jù)報(bào)的最大長(zhǎng)度限制是不同的,IP 協(xié)議通過(guò)給每個(gè) IP 數(shù)據(jù)報(bào)分配一個(gè)標(biāo)識(shí)符以及分段與組裝的相關(guān)信息,使得數(shù)據(jù)報(bào)在不同的網(wǎng)絡(luò)中能夠被傳輸,被分段后的 IP 數(shù)據(jù)報(bào)可以獨(dú)立地在網(wǎng)絡(luò)中進(jìn)行轉(zhuǎn)發(fā),在達(dá)到目標(biāo)主機(jī)后由目標(biāo)主機(jī)完成重組工作,恢復(fù)出原來(lái)的 IP 數(shù)據(jù)報(bào)。
傳輸層協(xié)議和網(wǎng)絡(luò)層協(xié)議有什么區(qū)別?
網(wǎng)絡(luò)層協(xié)議負(fù)責(zé)提供主機(jī)間的邏輯通信;傳輸層協(xié)議負(fù)責(zé)提供進(jìn)程間的邏輯通信。
49.IP 地址有哪些分類?
一個(gè) IP 地址在這鞥個(gè)互聯(lián)網(wǎng)范圍內(nèi)是惟一的,一般可以這么認(rèn)為,IP 地址 = {<網(wǎng)絡(luò)號(hào)>,<主機(jī)號(hào)>}。
網(wǎng)絡(luò)號(hào):它標(biāo)志主機(jī)所連接的網(wǎng)絡(luò)地址表示屬于互聯(lián)網(wǎng)的哪一個(gè)網(wǎng)絡(luò)。 主機(jī)號(hào):它標(biāo)志主機(jī)地址表示其屬于該網(wǎng)絡(luò)中的哪一臺(tái)主機(jī)。
IP 地址分為 A,B,C,D,E 五大類:
A 類地址 (1~126):以 0 開(kāi)頭,網(wǎng)絡(luò)號(hào)占前 8 位,主機(jī)號(hào)占后面 24 位。 B 類地址 (128~191):以 10 開(kāi)頭,網(wǎng)絡(luò)號(hào)占前 16 位,主機(jī)號(hào)占后面 16 位。 C 類地址 (192~223):以 110 開(kāi)頭,網(wǎng)絡(luò)號(hào)占前 24 位,主機(jī)號(hào)占后面 8 位。 D 類地址 (224~239):以 1110 開(kāi)頭,保留為多播地址。 E 類地址 (240~255):以 1111 開(kāi)頭,保留位為將來(lái)使用

50.域名和 IP 的關(guān)系?一個(gè) IP 可以對(duì)應(yīng)多個(gè)域名嗎?
IP 地址在同一個(gè)網(wǎng)絡(luò)中是惟一的,用來(lái)標(biāo)識(shí)每一個(gè)網(wǎng)絡(luò)上的設(shè)備,其相當(dāng)于一個(gè)人的身份證號(hào) 域名在同一個(gè)網(wǎng)絡(luò)中也是惟一的,就像是一個(gè)人的名字、綽號(hào)
假如你有多個(gè)不用的綽號(hào),你的朋友可以用其中任何一個(gè)綽號(hào)叫你,但你的身份證號(hào)碼卻是惟一的。但同時(shí)你的綽號(hào)也可能和別人重復(fù),假如你不在,有人叫你的綽號(hào),其它人可能就答應(yīng)了。
一個(gè)域名可以對(duì)應(yīng)多個(gè) IP,但這種情況 DNS 做負(fù)載均衡的,在用戶訪問(wèn)過(guò)程中,一個(gè)域名只能對(duì)應(yīng)一個(gè) IP。
而一個(gè) IP 卻可以對(duì)應(yīng)多個(gè)域名,是一對(duì)多的關(guān)系。
51.IPV4 地址不夠如何解決?
我們知道,IP 地址有 32 位,可以標(biāo)記 2 的 32 次方個(gè)地址,聽(tīng)起來(lái)很多,但是全球的網(wǎng)絡(luò)設(shè)備數(shù)量已經(jīng)遠(yuǎn)遠(yuǎn)超過(guò)這個(gè)數(shù)字,所以 IPV4 地址已經(jīng)不夠用了,那怎么解決呢?

DHCP:動(dòng)態(tài)主機(jī)配置協(xié)議,動(dòng)態(tài)分配 IP 地址,只給接入網(wǎng)絡(luò)的設(shè)備分配 IP 地址,因此同一個(gè) MAC 地址的設(shè)備,每次接入互聯(lián)網(wǎng)時(shí),得到的 IP 地址不一定是相同的,該協(xié)議使得空閑的 IP 地址可以得到充分利用。 CIDR:無(wú)類別域間路由。CIDR 消除了傳統(tǒng)的 A 類、B 類、C 類地址以及劃分子網(wǎng)的概念,因而更加有效地分配 IPv4 的地址空間,但無(wú)法從根本上解決地址耗盡的問(wèn)題。 NAT:網(wǎng)絡(luò)地址轉(zhuǎn)換協(xié)議,我們知道屬于不同局域網(wǎng)的主機(jī)可以使用相同的 IP 地址,從而一定程度上緩解了 IP 資源枯竭的問(wèn)題,然而主機(jī)在局域網(wǎng)中使用的 IP 地址是不能在公網(wǎng)中使用的,當(dāng)局域網(wǎng)主機(jī)想要與公網(wǎng)主機(jī)進(jìn)行通信時(shí),NAT 方法可以將該主機(jī) IP 地址轉(zhuǎn)換為全球 IP 地址。該協(xié)議能夠有效解決 IP 地址不足的問(wèn)題。 IPv6:作為接替 IPv4 的下一代互聯(lián)網(wǎng)協(xié)議,其可以實(shí)現(xiàn) 2 的 128 次方個(gè)地址,而這個(gè)數(shù)量級(jí),即使給地球上每一粒沙子都分配一個(gè) IP 地址也夠用,該協(xié)議能夠從根本上解決 IPv4 地址不夠用的問(wèn)題。
52.說(shuō)下 ARP 協(xié)議的工作過(guò)程?
ARP 協(xié)議,Address Resolution Protocol,地址解析協(xié)議,它是用于實(shí)現(xiàn) IP 地址到 MAC 地址的映射。

首先,每臺(tái)主機(jī)都會(huì)在自己的 ARP 緩沖區(qū)中建立一個(gè) ARP 列表,以表示 IP 地址和 MAC 地址的對(duì)應(yīng)關(guān)系。 當(dāng)源主機(jī)需要將一個(gè)數(shù)據(jù)包要發(fā)送到目的主機(jī)時(shí),會(huì)首先檢查自己的 ARP 列表,是否存在該 IP 地址對(duì)應(yīng)的 MAC 地址;如果有﹐就直接將數(shù)據(jù)包發(fā)送到這個(gè) MAC 地址;如果沒(méi)有,就向本地網(wǎng)段發(fā)起一個(gè) ARP 請(qǐng)求的廣播包,查詢此目的主機(jī)對(duì)應(yīng)的 MAC 地址。此 ARP 請(qǐng)求的數(shù)據(jù)包里,包括源主機(jī)的 IP 地址、硬件地址、以及目的主機(jī)的 IP 地址。 網(wǎng)絡(luò)中所有的主機(jī)收到這個(gè) ARP 請(qǐng)求后,會(huì)檢查數(shù)據(jù)包中的目的 IP 是否和自己的 IP 地址一致。如果不相同,就會(huì)忽略此數(shù)據(jù)包;如果相同,該主機(jī)首先將發(fā)送端的 MAC 地址和 IP 地址添加到自己的 ARP 列表中,如果 ARP 表中已經(jīng)存在該 IP 的信息,則將其覆蓋,然后給源主機(jī)發(fā)送一個(gè) ARP 響應(yīng)數(shù)據(jù)包,告訴對(duì)方自己是它需要查找的 MAC 地址。 源主機(jī)收到這個(gè) ARP 響應(yīng)數(shù)據(jù)包后,將得到的目的主機(jī)的 IP 地址和 MAC 地址添加到自己的 ARP 列表中,并利用此信息開(kāi)始數(shù)據(jù)的傳輸。如果源主機(jī)一直沒(méi)有收到 ARP 響應(yīng)數(shù)據(jù)包,表示 ARP 查詢失敗。
53.為什么既有 IP 地址,又有 MAC 地址?
MAC 地址和 IP 地址都有什么作用?
MAC 地址是數(shù)據(jù)鏈路層和物理層使用的地址,是寫(xiě)在網(wǎng)卡上的物理地址,用來(lái)定義網(wǎng)絡(luò)設(shè)備的位置,不可變更。 IP 地址是網(wǎng)絡(luò)層和以上各層使用的地址,是一種邏輯地址。IP 地址用來(lái)區(qū)別網(wǎng)絡(luò)上的計(jì)算機(jī)。
為什么有了 MAC 地址還需要 IP 地址?
如果我們只使用 MAC 地址進(jìn)行尋址的話,我們需要路由器記住每個(gè) MAC 地址屬于哪個(gè)子網(wǎng),不然一次路由器收到數(shù)據(jù)包都要滿世界尋找目的 MAC 地址。而我們知道 MAC 地址的長(zhǎng)度為 48 位,也就是最多共有 2 的 48 次方個(gè) MAC 地址,這就意味著每個(gè)路由器需要 256T 的內(nèi)存,顯然是不現(xiàn)實(shí)的。
和 MAC 地址不同,IP 地址是和地域相關(guān)的,在一個(gè)子網(wǎng)中的設(shè)備,我們給其分配的 IP 地址前綴都是一樣的,這樣路由器就能根據(jù) IP 地址的前綴知道這個(gè)設(shè)備屬于哪個(gè)子網(wǎng),剩下的尋址就交給子網(wǎng)內(nèi)部實(shí)現(xiàn),從而大大減少了路由器所需要的內(nèi)存。
為什么有了 IP 地址還需要 MAC 地址?

只有當(dāng)設(shè)備連入網(wǎng)絡(luò)時(shí),才能根據(jù)他進(jìn)入了哪個(gè)子網(wǎng)來(lái)為其分配 IP 地址,在設(shè)備還沒(méi)有 IP 地址的時(shí)候,或者在分配 IP 的過(guò)程中。我們需要 MAC 地址來(lái)區(qū)分不同的設(shè)備。 IP 地址可以比作為地址,MAC 地址為收件人,在一次通信過(guò)程中,兩者是缺一不可的。
54.ICMP 協(xié)議的功能?
ICMP(Internet Control Message Protocol) ,網(wǎng)際控制報(bào)文協(xié)議。
ICMP 協(xié)議是一種面向無(wú)連接的協(xié)議,用于傳輸出錯(cuò)報(bào)告控制信息。 它是一個(gè)非常重要的協(xié)議,它對(duì)于網(wǎng)絡(luò)安全具有極其重要的意義。它屬于網(wǎng)絡(luò)層協(xié)議,主要用于在主機(jī)與路由器之間傳遞控制信息,包括報(bào)告錯(cuò)誤、交換受限控制和狀態(tài)信息等。 當(dāng)遇到 IP 數(shù)據(jù)無(wú)法訪問(wèn)目標(biāo)、IP 路由器無(wú)法按當(dāng)前的傳輸速率轉(zhuǎn)發(fā)數(shù)據(jù)包等情況時(shí),會(huì)自動(dòng)發(fā)送 ICMP 消息。
比如我們?nèi)粘J褂玫帽容^多的 ping,就是基于 ICMP 的。
55.說(shuō)下 ping 的原理?
ping,Packet Internet Groper,是一種因特網(wǎng)包探索器,用于測(cè)試網(wǎng)絡(luò)連接量的程序。Ping 是工作在 TCP/IP 網(wǎng)絡(luò)體系結(jié)構(gòu)中應(yīng)用層的一個(gè)服務(wù)命令, 主要是向特定的目的主機(jī)發(fā)送 ICMP(Internet Control Message Protocol 因特網(wǎng)報(bào)文控制協(xié)議) 請(qǐng)求報(bào)文,測(cè)試目的站是否可達(dá)及了解其有關(guān)狀態(tài)。

一般來(lái)說(shuō),ping 可以用來(lái)檢測(cè)網(wǎng)絡(luò)通不通。它是基于ICMP協(xié)議工作的。假設(shè)機(jī)器 A ping 機(jī)器 B,工作過(guò)程如下:
ping 通知系統(tǒng),新建一個(gè)固定格式的 ICMP 請(qǐng)求數(shù)據(jù)包 ICMP 協(xié)議,將該數(shù)據(jù)包和目標(biāo)機(jī)器 B 的 IP 地址打包,一起轉(zhuǎn)交給 IP 協(xié)議層 IP 層協(xié)議將本機(jī) IP 地址為源地址,機(jī)器 B 的 IP 地址為目標(biāo)地址,加上一些其他的控制信息,構(gòu)建一個(gè) IP 數(shù)據(jù)包 先獲取目標(biāo)機(jī)器 B 的 MAC 地址。 數(shù)據(jù)鏈路層構(gòu)建一個(gè)數(shù)據(jù)幀,目的地址是 IP 層傳過(guò)來(lái)的 MAC 地址,源地址是本機(jī)的 MAC 地址 機(jī)器 B 收到后,對(duì)比目標(biāo)地址,和自己本機(jī)的 MAC 地址是否一致,符合就處理返回,不符合就丟棄。 根據(jù)目的主機(jī)返回的 ICMP 回送回答報(bào)文中的時(shí)間戳,從而計(jì)算出往返時(shí)間 最終顯示結(jié)果有這幾項(xiàng):發(fā)送到目的主機(jī)的 IP 地址、發(fā)送 & 收到 & 丟失的分組數(shù)、往返時(shí)間的最小、最大 & 平均值
網(wǎng)絡(luò)安全
56.說(shuō)說(shuō)有哪些安全攻擊?
網(wǎng)絡(luò)安全攻擊主要分為兩種類型,被動(dòng)攻擊和主動(dòng)攻擊:

被動(dòng)攻擊:是指攻擊者從網(wǎng)絡(luò)上竊聽(tīng)他人的通信內(nèi)容,通常把這類攻擊稱為截獲,被動(dòng)攻擊主要有兩種形式:消息內(nèi)容泄露攻擊和流量分析攻擊。由于攻擊者沒(méi)有修改數(shù)據(jù),使得這種攻擊很難被檢測(cè)到。
主動(dòng)攻擊:直接對(duì)現(xiàn)有的數(shù)據(jù)和服務(wù)造成影響,常見(jiàn)的主動(dòng)攻擊類型有:
篡改:攻擊者故意篡改網(wǎng)絡(luò)上送的報(bào)文,甚至把完全偽造的報(bào)文傳送給接收方。
惡意程序:惡意程序種類繁多,包括計(jì)算機(jī)病毒、計(jì)算機(jī)蠕蟲(chóng)、特洛伊木馬、后門入侵、流氓軟件等等。
拒絕服務(wù) Dos:攻擊者向服務(wù)器不停地發(fā)送分組,使服務(wù)器無(wú)法提供正常服務(wù)。
57.DNS 劫持了解嗎?
DNS 劫持即域名劫持,是通過(guò)將原域名對(duì)應(yīng)的 IP 地址進(jìn)行替換,從而使用戶訪問(wèn)到錯(cuò)誤的網(wǎng)站,或者使用戶無(wú)法正常訪問(wèn)網(wǎng)站的一種攻擊方式。

域名劫持往往只能在特定的網(wǎng)絡(luò)范圍內(nèi)進(jìn)行,范圍外的 DNS 服務(wù)器能夠返回正常的 IP 地址。攻擊者可以冒充原域名所屬機(jī)構(gòu),通過(guò)電子郵件的方式修改組織機(jī)構(gòu)的域名注冊(cè)信息,或者將域名轉(zhuǎn)讓給其它主持,并將新的域名信息保存在所指定的 DNS 服務(wù)器中,從而使用戶無(wú)法對(duì)原域名來(lái)進(jìn)行解析以訪問(wèn)目標(biāo)地址。
DNS 劫持的步驟是什么樣的?
獲取要劫持的域名信息:攻擊者會(huì)首先訪問(wèn)域名查詢要劫持的站點(diǎn)的域名信息。 控制域名響應(yīng)的 E-Mail 賬號(hào):在獲取到域名信息后,攻擊者通過(guò)暴力破解或者專門的方法破解公司注冊(cè)域名時(shí)使用的 E-mail 賬號(hào)所對(duì)應(yīng)的密碼,更高級(jí)的攻擊者甚至能夠直接對(duì) E-Mail 進(jìn)行信息竊取。 修改注冊(cè)信息:當(dāng)攻擊者破解了 E-Mail 后,會(huì)利用相關(guān)的更改功能修改該域名的注冊(cè)信息,包括域名擁有者信息,DNS 服務(wù)器信息等。 使用 E-Mail 收發(fā)確認(rèn)函:在修改完注冊(cè)信息后,攻擊者 E-Mail 在真正擁有者之前收到修改域名注冊(cè)信息的相關(guān)確認(rèn)信息,并回復(fù)確認(rèn)修改文件,待網(wǎng)絡(luò)公司恢復(fù)已成功修改信件后,攻擊者便成功完成 DNS 劫持。
怎么應(yīng)對(duì) DNS 劫持?
直接通過(guò) IP 地址訪問(wèn)網(wǎng)站,避開(kāi) DNS 劫持 由于域名劫持往往只能在特定的網(wǎng)絡(luò)范圍內(nèi)進(jìn)行,因此一些高級(jí)用戶可以通過(guò)網(wǎng)絡(luò)設(shè)置讓 DNS 指向正常的域名服務(wù)器以實(shí)現(xiàn)對(duì)目標(biāo)網(wǎng)址的正常訪問(wèn),例如計(jì)算機(jī)首選 DNS 服務(wù)器的地址固定為 8.8.8.8。
58.什么是 CSRF 攻擊?如何避免?
什么是 CSRF 攻擊?
CSRF,跨站請(qǐng)求偽造(英文全稱是 Cross-site request forgery),是一種挾持用戶在當(dāng)前已登錄的 Web 應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。
CSRF 是如何攻擊的呢?
來(lái)看一個(gè)例子:

用戶登陸銀行,沒(méi)有退出,瀏覽器包含了 用戶 在銀行的身份認(rèn)證信息。 攻擊者將偽造的轉(zhuǎn)賬請(qǐng)求,包含在在帖子 用戶在銀行網(wǎng)站保持登陸的情況下,瀏覽帖子 將偽造的轉(zhuǎn)賬請(qǐng)求連同身份認(rèn)證信息,發(fā)送到銀行網(wǎng)站 銀行網(wǎng)站看到身份認(rèn)證信息,以為就是 用戶的合法操作,最后造成用戶資金損失。
怎么應(yīng)對(duì) CSRF 攻擊呢?
檢查 Referer 字段
HTTP 頭中的 Referer 字段記錄了該 HTTP 請(qǐng)求的來(lái)源地址。在通常情況下,訪問(wèn)一個(gè)安全受限頁(yè)面的請(qǐng)求來(lái)自于同一個(gè)網(wǎng)站,而如果黑客要對(duì)其實(shí)施 CSRF 攻擊,他一般只能在他自己的網(wǎng)站構(gòu)造請(qǐng)求。因此,可以通過(guò)驗(yàn)證 Referer 值來(lái)防御 CSRF 攻擊。
添加校驗(yàn) token
以在 HTTP 請(qǐng)求中以參數(shù)的形式加入一個(gè)隨機(jī)產(chǎn)生的 token,并在服務(wù)器端建立一個(gè)攔截器來(lái)驗(yàn)證這個(gè) token,如果請(qǐng)求中沒(méi)有 token 或者 token 內(nèi)容不正確,則認(rèn)為可能是 CSRF 攻擊而拒絕該請(qǐng)求。
敏感操作多重校驗(yàn)
對(duì)一些敏感的操作,除了需要校驗(yàn)用戶的認(rèn)證信息,還可以通過(guò)郵箱確認(rèn)、驗(yàn)證碼確認(rèn)這樣的方式多重校驗(yàn)。
59.什么是 DoS、DDoS、DRDoS 攻擊?

DOS: (Denial of Service), 翻譯過(guò)來(lái)就是拒絕服務(wù), 一切能引起拒絕 行為的攻擊都被稱為 DOS 攻擊。最常見(jiàn)的 DoS 攻擊就有計(jì)算機(jī)網(wǎng)絡(luò)寬帶攻擊、連通性攻擊。 DDoS: (Distributed Denial of Service),翻譯過(guò)來(lái)是分布式拒絕服務(wù)。是指處于不同位置的多個(gè)攻擊者同時(shí)向一個(gè)或幾個(gè)目標(biāo)發(fā)動(dòng)攻擊,或者一個(gè)攻擊者控制了位于不同位置的多臺(tái)機(jī)器,并利用這些機(jī)器對(duì)受害者同時(shí)實(shí)施攻擊。
主要形式有流量攻擊和資源耗盡攻擊,常見(jiàn)的 DDoS 攻擊有:SYN Flood、Ping of Death、ACK Flood、UDP Flood 等。
DRDoS: (Distributed Reflection Denial of Service),中文是分布式反射拒絕服務(wù),該方式靠的是發(fā)送大量帶有被害者 IP 地址的數(shù)據(jù)包給攻擊主機(jī),然后攻擊主機(jī)對(duì) IP 地址源做出大量回應(yīng),從而形成拒絕服務(wù)攻擊。
如何防范 DDoS?
針對(duì) DDoS 中的流量攻擊,最直接的方法是增加帶寬,理論上只要帶寬大于攻擊流量就可以了,但是這種方法成本非常高。在有充足帶寬的前提下,我們應(yīng)該盡量提升路由器、網(wǎng)卡、交換機(jī)等硬件設(shè)施的配置。
針對(duì)資源耗盡攻擊,我們可以升級(jí)主機(jī)服務(wù)器硬件,在網(wǎng)絡(luò)帶寬得到保證的前提下,使得服務(wù)器能夠有效對(duì)抗海量的 SYN 攻擊包。我們也可以安裝專業(yè)的抗 DDoS 防火墻,從而對(duì)抗 SYN Flood 等流量型攻擊。瓷碗,負(fù)載均衡,CDN 等技術(shù)都能有效對(duì)抗 DDos 攻擊。
60.什么是 XSS 攻擊,如何避免?
XSS 攻擊也是比較常見(jiàn),XSS,叫跨站腳本攻擊(Cross-Site Scripting),因?yàn)闀?huì)與層疊樣式表 (Cascading Style Sheets, CSS) 的縮寫(xiě)混淆,因此有人將跨站腳本攻擊縮寫(xiě)為 XSS。它指的是惡意攻擊者往 Web 頁(yè)面里插入惡意 html 代碼,當(dāng)用戶瀏覽網(wǎng)頁(yè)的時(shí)候,嵌入其中 Web 里面的 html 代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的特殊目的。
XSS 攻擊一般分三種類型:存儲(chǔ)型 、反射型 、DOM 型 XSS
XSS 是如何攻擊的呢?
簡(jiǎn)單說(shuō),XSS 的攻擊方式就是想辦法“教唆”用戶的瀏覽器去執(zhí)行一些這個(gè)網(wǎng)頁(yè)中原本不存在的前端代碼。
拿反射型舉個(gè)例子吧,流程圖如下:
攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼。 用戶打開(kāi)帶有惡意代碼的 URL 時(shí),訪問(wèn)正常網(wǎng)站服務(wù)器 網(wǎng)站服務(wù)端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器。 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行,請(qǐng)求惡意服務(wù)器,發(fā)送用戶數(shù)據(jù) 攻擊者就可以竊取用戶的數(shù)據(jù),以此冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。

如何應(yīng)對(duì) XSS 攻擊?
對(duì)輸入進(jìn)行過(guò)濾,過(guò)濾標(biāo)簽等,只允許合法值。 HTML 轉(zhuǎn)義 對(duì)于鏈接跳轉(zhuǎn),如 <a href="xxx"等,要校驗(yàn)內(nèi)容,禁止以 script 開(kāi)頭的非法鏈接。限制輸入長(zhǎng)度
61.對(duì)稱加密與非對(duì)稱加密有什么區(qū)別?
對(duì)稱加密:指加密和解密使用同一密鑰,優(yōu)點(diǎn)是運(yùn)算速度較快,缺點(diǎn)是如何安全將密鑰傳輸給另一方。常見(jiàn)的對(duì)稱加密算法有:DES、AES 等。

非對(duì)稱加密:指的是加密和解密使用不同的密鑰(即公鑰和私鑰)。公鑰與私鑰是成對(duì)存在的,如果用公鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有對(duì)應(yīng)的私鑰才能解密。常見(jiàn)的非對(duì)稱加密算法有 RSA。

62.RSA 和 AES 算法有什么區(qū)別?
RSA
采用非對(duì)稱加密的方式,采用公鑰進(jìn)行加密,私鑰解密的形式。其私鑰長(zhǎng)度一般較長(zhǎng),由于需要大數(shù)的乘冪求模等運(yùn)算,其運(yùn)算速度較慢,不合適大量數(shù)據(jù)文件加密。
AES
采用對(duì)稱加密的方式,其秘鑰長(zhǎng)度最長(zhǎng)只有 256 個(gè)比特,加密和解密速度較快,易于硬件實(shí)現(xiàn)。由于是對(duì)稱加密,通信雙方在進(jìn)行數(shù)據(jù)傳輸前需要獲知加密密鑰。
沒(méi)有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧?kù)o的港灣,我是不系之舟。
