前言
最近和一同學聊天,他想換工作,然后去面了一家大廠。當時,他在簡歷上寫着精通TCP/IP,本着對TCP協議稍有了解,面試官也不會深問的想法,就寫了精通二字。沒想到,大意了
關注公眾號,一起交流,微信搜一搜: 潛行前行

github地址,感謝star
開場
朋友約的是十點半的面試,提前了十分鍾到,然后安靜地坐在沙發等待,順便回憶下之前看的資料。快到十點半時,一個高瘦,穿着格子衫的男子推開門而進,說了句“你好,我們來開始面試吧!”,朋友不失禮貌地笑着回了句“行”
面試官:看你簡歷說精通TCP和IP,那我們來討論下網絡模型和TCP、IP協議,講下你的理解先
- 朋友(怎么一上來就問TCP,不按套路出牌啊,不該問問java基礎嗎?不過常規題,我還行)
- 朋友:網絡模型一般分七層:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層。應用層的協議包括HTTP、FTP、SMTP,而TCP屬於傳輸層,IP協議則屬於網絡層
- 朋友:TCP/IP網絡模型層次由上到下,層層包裝,每一層都對應不同的協議解析,我來畫個圖
面試官:看你畫的圖,TCP有自己的首部結構,這都有哪些字段,最好說說它們的作用
- 朋友(什么鬼!當我百度詞典,這怎么記得住?等等,昨天晚上好像看過,有印象)
- 朋友:繼續畫個圖,直觀點
- 朋友:TCP首部結構先是16位的源端口號和目標端口號、接着是32位的序列號和確認號。再下面就是4bit的頭部長度和6個bit的保留位及6bit的標志位
- 朋友:16位的屬性則有窗口大小(控制發送窗口),檢驗和(校驗數據段是否未被修改)及緊急指針。最后是選項,其長度由頭部長度決定
- 朋友:詳細說下序列號,它是TCP報文段的一數字編號,為保證TCP可靠連接,每一個發送的數據段都要加上序列號。建立連接時,兩端都會隨機生成一個初始序列號。而確認號而是和序列號配合使用的,應答某次請求時,則返回一個確認號,它的值等於對方請求序列號加1
- 朋友:而6個標志位分別是,URG:這是條緊急信息,ACK:應答消息,PSH:緩沖區尚未填滿,RST:重置連接,SYN:建立連接消息標志,FIN:連接關閉通知信息
- 朋友:窗口大小是接收端用來控制發送端的滑動窗口大小
面試官:那TCP和UDP有什么區別
- 朋友(松了一口氣)
- 朋友:1)連接方面:TCP面向連接。UDP是無連接的,發送數據之前不需要建立連接
- 朋友:2)安全方面:TCP提供可靠的服務,保證傳送的數據,無差錯,不丟失,不重復,且按序到達。UDP則是盡最大努力交付,不保證可靠交付
- 朋友:3)傳輸效率:TCP傳輸效率相對較低,UDP傳輸效率高
面試官:剛才你說TCP是可靠的連接,它是怎么實現的
- 朋友:TCP的連接是基於三次握手,而斷開則是四次揮手
- 朋友:為了保障數據不丟失及錯誤(可靠性),它有報文校驗、ACK應答、超時重傳(發送方)、失序數據重傳(接收方)、丟棄重復數據、流量控制(滑動窗口)和擁塞控制等機制
面試官:具體說一說三次握手和四次揮手機制
- 朋友(又是常規題,曬曬水啦)
- 朋友:TCP是可靠的雙向通道,所以需要三次握手和四次揮手,我來畫個圖
- 三次握手
- 四次揮手
- 朋友:提前搶答下,關閉連接時需要四次揮手,比建立時多一次,是因為被動關閉端或許還有數據沒被送出去,不能像握手時一樣,第二次握手既是發起握手也是響應握手
面試官:如果沒有三次握手會有什么問題呢
- 朋友:如果只有兩次握手,client發連接請求后不會再ACK服務端的SYN
- 朋友:此時若客戶端因為自身原因判斷建立連接失敗,可能會重復建立TCP連接,而服務端卻會認為那些被client丟棄的TCP還是有效,會白白浪費資源
面試官:TIME_WAIT和CLOSE_WAIT的區別在哪
- 朋友:CLOSE_WAIT是被動關閉形成的;當對方close socket而發送FIN報文過來時,回應ACK之后進入CLOSE_WAIT狀態。隨后檢查是否存在未傳輸數據,如果沒有則發起第三次揮手,發送FIN報文給對方,進入LAST_ACK狀態並等待對方ACK報文到來
- 朋友:TIME_WAIT是主動關閉連接方式形成的;處於FIN_WAIT_2狀態時,收到對方FIN報文后進入TIME_WAIT狀態;之后再等待兩個MSL(Maximum Segment Lifetime:報文最大生存時間)
面試官:TIME_WAIT的作用呢,還有為啥狀態時間要保持兩個MSL
- 朋友(這問得太深了吧,老哥。還好昨天偷偷補課了)
- 朋友:1)TIME_WAIT的作用是為了保證最后一次揮手的ACK報文能送達給對方,如果ACK丟失,對方會超時重傳FIN,主動關閉端會再次響應ACK過去;如果沒有TIME_WAIT狀態,直接關閉,對方重傳的FIN報文則被響應一個RST報文,此RST會被動關閉端被解析成錯誤
- 朋友:2)存在兩個連接,第一個連接正常關閉,第二相同的連接緊接着建立;如果第一個連接的迷路報文到來,則會干擾第二連接,等待兩個MSL則可以讓上次連接的報文數據消逝在網絡后
面試官:剛才你還有提到擁塞控制,TCP協議用什么方式去解決擁塞的
- 朋友:第一方式是慢啟動和擁塞避免
- 朋友:1)慢啟動,TCP發送端會維護一個擁塞窗口(congestionwindow),簡稱為cwnd。擁塞窗口初始為1個報文段,每經過一次RTT(數據完全發送完到確認的時間),窗口大小翻倍(指數增長,只是前期慢)
- 朋友:2)擁塞避免,它思路是讓擁塞窗口cwnd緩慢增大,發送方的cwnd達到閥值ssthresh(初始值由系統決定的)之后,每經過一個RTT就把擁塞窗口加一,而不是加倍(收到兩個或四個確認,都是cwnd+1),cwnd呈線性增加(加法增大)
- 朋友:(畫個圖好解析)
- 朋友:如果遇到網絡擁塞,擁塞窗口閥值ssthresh減半,cwnd設置為1,重新進入慢啟動階段
面試官:那擁塞控制還有其他什么方式呢
- 朋友:快重傳和快恢復
- 朋友:1)快重傳是當接收方收到了一個失序的報文,則立馬報告給發送方,趕緊重傳
- 朋友:假如接收方M1收到了,M2沒有收到,之后的M3、M4、M5又發送了,此時接收方一共連續給發送方反饋了3個M1確認報文。那么快重傳規定,發送方只要連續收到3個重復確認,立即重傳對方發來的M2(重復確認報文的后一個報文)
- 朋友:2)快恢復
- 朋友:當發送方連續收到三個重復確認,ssthresh減半;由於發送方可能認為網絡現在沒有擁塞,因此與慢啟動不同,把cwnd值設置為ssthresh減半之后的值,然后執行擁塞避免算法,cwnd線性增大
- 朋友:(再來一圖)
面試官:知道滑動窗口不,客戶端和服務端控制滑動窗口的過程是怎樣的
- 朋友:接收端將自己可以接收的緩沖區大小放入TCP首部中的“窗口大小”字段,通過ACK報文來通知發送端,滑動窗口是接收端用來控制發送端發送數據的大小,從而達到流量控制
- 朋友:其實發送方的窗口上限,是取值擁塞窗口和滑動窗口兩者的最小值
面試官:那你知道滑動窗口和擁塞窗口有什么區別不
- 朋友:相同點都是控制丟包現象,實現機制都是讓發送方發得慢一點
- 朋友:不同點在於控制的對象不同
- 朋友:1)流量控制的對象是接收方,怕發送方發的太快,使得接收方來不及處理
- 朋友:2)擁塞控制的對象是網絡,怕發送方發的太快,造成網絡擁塞,使得網絡來不及處理
面試官:TCP的粘包和拆包問題,你怎么看
- 朋友:程序需要發送的數據大小和TCP報文段能發送MSS(Maximum Segment Size,最大報文長度)是不一樣的
- 朋友:大於MSS時,而需要把程序數據拆分為多個TCP報文段,稱之為拆包;小於時,則會考慮合並多個程序數據為一個TCP報文段,則是粘包;其中MSS = TCP報文段長度-TCP首部長度
- 朋友:在IP協議層或者鏈路層、物理層,都存在拆包、粘包現象
面試官:那解決粘包和拆包的方法都有哪些?
- 朋友:1)在數據尾部增加特殊字符進行分割
- 朋友:2)將數據定為固定大小
- 朋友:3)將數據分為兩部分,一部分是頭部,一部分是內容體;其中頭部結構大小固定,且有一個字段聲明內容體的大小
面試官:SYN Flood了解嗎
- 朋友:SYN Flood 偽造 SYN 報文向服務器發起連接,服務器在收到報文后用 SYN_ACK 應答,此應答發出去后,不會收到 ACK 報文,造成一個半連接
- 朋友:若攻擊者發送大量這樣的報文,會在被攻擊主機上出現大量的半連接,耗盡其資源,使正常的用戶無法訪問,直到半連接超時
面試官:對TCP的掌握挺不錯的,下面問下HTTP的知識。你知道一次HTTP請求,程序一般經歷了哪幾個步驟?
- 朋友:1)解析域名 -> 2)發起TCP三次握手,建立連接 -> 3)基於TCP發起HTTP請求 -> 4)服務器響應HTTP請求,並返回數據 -> 5)客戶端解析返回數據
面試官:HTTP有哪幾種響應狀態碼,列舉幾個你熟悉的
- 朋友:大概有以下幾種
- 200:表示成功正常請求
- 400:語義有誤,一般是請求格式不對
- 401:需求用戶驗證權限,一般是證書token沒通過認證
- 403:拒絕提供服務
- 404:資源不存在
- 500:服務器錯誤
- 503:服務器臨時維護,過載;可恢復
面試官:不錯,再考考你,session和cookie有什么區別
- 朋友:1)存儲位置不同,cookie是保存在客戶端的數據;session的數據存放在服務器上
- 朋友:2)存儲容量不同,單個cookie保存的數據小,一個站點最多保存20個Cookie;對於session來說並沒有上限
- 朋友:3)存儲方式不同,cookie中只能保管ASCII字符串;session中能夠存儲任何類型的數據
- 朋友:4)隱私策略不同,cookie對客戶端是可見的;session存儲在服務器上,對客戶端是透明對
- 朋友:5)有效期上不同,cookie可以長期有效存在;session依賴於名為JSESSIONID的cookie,過期時間默認為-1,只需關閉窗口該session就會失效
- 朋友:6)跨域支持上不同,cookie支持跨域名訪問;session不支持跨域名訪問
面試官:不錯,那你了解什么是HTTP分塊傳送嗎
- 朋友:分塊傳送是HTTP的一種傳輸機制,允許服務端發送給客戶端的數據分成多個部分,該協議在HTTP/1.1提供
面試官:HTTP分塊傳送有什么好處
- 朋友:HTTP分塊傳輸編碼允許服務器為動態生成的內容維持HTTP持久連接
- 朋友:分塊傳輸編碼允許服務器在最后發送消息頭字段。對於那些頭字段值在內容被生成之前無法知道的情形非常重要,例如消息的內容要使用散列進行簽名
- 朋友:HTTP服務器有時使用壓縮 (gzip或deflate)以縮短傳輸花費的時間。分塊傳輸編碼可以用來分隔壓縮對象的多個部分。在這種情況下,塊不是分別壓縮的,而是整個負載進行壓縮。分塊編碼有利於一邊進行壓縮一邊發送數據
面試官:HTTP的長連接你怎么理解
- 朋友:長連接是指客戶端和服務建立TCP連接后,它們之間的連接會持續存在,不會因為一次HTTP請求后關閉,后續的請求也是用這個連接
- 朋友:長連接可以省去TCP的建立和關閉操作,對於頻繁請求的客戶端適合使用長連接,但是注意惡意的長連接導致服務受損(建議內部服務之間使用)
面試官:HTTP是安全的嗎?怎么做到安全的HTTP協議傳輸
- 朋友:並非安全,HTTP傳輸的數據都是明文的,容易被第三方截取;要做安全傳輸數據,可以使用HTTP的升級版HTTPS協議
面試官:HTTPS和HTTP的區別,你是怎么理解的
- 朋友:1)http協議的連接是無狀態的,明文傳輸
- 朋友:2)HTTPS則是由SSL/TLS+HTTP協議構建的有加密傳輸、身份認證的網絡協議
面試官:SSL/TLS是什么,HTTPS的安全性是怎樣實現的?
- 朋友:SSL(Secure Socket Layer 安全套接層)是基於HTTPS下的一個協議加密層,保障數據私密性。TLS(Transport Layer Security)則是升級版的SSL
- 朋友:https在http基礎加了一層安全認證及加密層TLS或者SSL,它首先會通過安全層進行ca證書認證,正確獲取服務端的公鑰
- 朋友:接着客戶端會通過公鑰和服務端確認一種加密算法,后面的數據則可以使用該加密算法對數據進行加密