阿里雲後端C/C++實習生面試,本人本科大三網絡安全專業,總結了一下面試中關於TCP/IP的相關問題,整理如下,期間參考的其他博客我會列出源地址。我儘量做一些自己的理解後的整理的答案,以面試中一問一答的形式呈現。可能因爲我菜,有些問題沒有問得很深入。可能有不對的地方,歡迎在評論區留言指出。
讓我們開始吧~
流量控制+擁塞控制
參考鏈接:https://zhuanlan.zhihu.com/p/37379780
流量控制:
流量控制的原因?
由於本地數據包傳輸過快,可能導致接收方來不及接受發送方發出的大量數據包。爲了避免這種現象發生,需要發送方控制發送數據包的速度,因此需要“流量控制”。
如何才能做到流量控制?協議如何實現?
主要的方式就是接收方返回的 ACK 中會包含自己的接收窗口的大小,並且利用大小來控制發送方的數據發送。當發送方注意到自己發送的數據包序號超過接收方能接受的窗口大小時,停止發送數據包。
擁塞控制
擁塞控制的原因?簡單描述一下原理?
需要進行擁塞控制的原因往往是因爲網絡的問題,可能某些時刻如雙十一期間,某些站點或者服務器的訪問量超過了網絡能承載的範圍,在隊列已滿的時候,爲了保證公平,會採用隨機丟包的方式來減輕網絡壓力。當TCP/IP協議檢測到網絡開始隨機丟包時,就通過擁塞控制來調整發包速率,減輕網絡負擔。
當發送方發現丟包了會怎麼做?
現在一般採用TCP Reno版本,也就是發包速率減半,然後再線性增加直到再出現丟包,如此循環。
三次握手
https://www.cnblogs.com/quehualin/p/10409607.html
三次握手中,可能會遇到什麼樣的情況?如何應對?
鏈接建立前:
1.SYN丟失、或者第一個迴應的ACK沒有被收到:發送方不斷嘗試發送syn,直到收到ack;忍受時間閾值:75s
2.接收方收到SYN,發出ACK包,此ACK包丟失:發送方同1中不斷嘗試,接收方超過時間沒有收到第三步握手的SEQ+ACK包會不斷重複發出ACK。忍受時間閾值與1相同。
3.發送方收到第二步的ACK包,狀態變爲ESTABLISHED,發出第三步的SEQ+ACK,若此包丟失:那麼發送端該TCP連接的狀態爲SYN_RECV,並且依次等待3秒、6秒、12秒後重新發送SYN+ACK包,以便重新發送ACK包。發送端重發SYN+ACK包的次數,可以通過設/proc/sys/net/ipv4/tcp_synack_retries修改,默認值爲5。如果重發指定次數後,仍然未收到ACK應答,那麼一段時間後,發送方關閉連接。
https://www.nowcoder.com/tutorial/93/e1b14ab2b40a4ef98d9e55830eb48d66
TCP/IP是如何保證協議穩定的?
(1)序列號、確認應答、超時重傳
(2)窗口控制與高速重發控制/快速重傳(重複確認應答)
(3)擁塞控制
在上述(2)中重複確認應答的過程中,採用什麼樣的方式確認?
接收方發送ACK指示下一個期待接收到的包。
如果上述ACK包丟了該怎麼辦?
以倍增的時間如3s,6s,12s……發送方不斷重複發送上一個ACK中指示的包,直到收到新的ACK包,若超過一定時間閾值仍然沒有收到ACK確認,斷開連接,以減小網絡的資源浪費。(我忘了時間閾值是20min還是2h)
四次揮手
面試官沒有細問我這個,就問我知不知道,我說知道,可能我前面答得比較好,他說那OK。那我也複製粘貼一下:
由於TCP連接時全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務後,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。
1.數據傳輸結束後,客戶端的應用進程發出連接釋放報文段,並停止發送數據,客戶端進入FIN_WAIT_1狀態,此時客戶端依然可以接收服務器發送來的數據。
2.服務器接收到FIN後,發送一個ACK給客戶端,確認序號爲收到的序號+1,服務器進入CLOSE_WAIT狀態。客戶端收到後進入FIN_WAIT_2狀態。
3.當服務器沒有數據要發送時,服務器發送一個FIN報文,此時服務器進入LAST_ACK狀態,等待客戶端的確認
4.客戶端收到服務器的FIN報文後,給服務器發送一個ACK報文,確認序列號爲收到的序號+1。此時客戶端進入TIME_WAIT狀態,等待2MSL(MSL:報文段最大生存時間),然後關閉連接。
爲什麼揮手需要四次但是握手只用三次?
揮手時FIN和ACK分別發送。
接上一問, 爲什麼要分別發送,不能和建立鏈接時一樣一起發送嗎?
1、當客戶端確認發送完數據且知道服務器已經接收完了,想要關閉發送數據口(當然確認信號還是可以發),就會發FIN給服務器。
2、服務器收到客戶端發送的FIN,表示收到了,就會發送ACK回覆。
3、但這時候服務器可能還在發送數據,沒有想要關閉數據口的意思,所以服務器的FIN與ACK不是同時發送的,而是等到服務器數據發送完了,纔會發送FIN給客戶端。
4、客戶端收到服務器發來的FIN,知道服務器的數據也發送完了,回覆ACK, 客戶端等待2MSL以後,沒有收到服務器傳來的任何消息,知道服務器已經收到自己的ACK了,客戶端就關閉鏈接,服務器也關閉鏈接了。
http與https
爲什麼需要https?
http有很多缺點,現在很多事情需要更高更好的安全,而運算速度的提升使得額外開銷可以被接受,https能夠更加做到安全,所以會被採用。
https是怎麼實現安全傳輸的?
通過SSL和TSL協議。HTTPS = HTTP + SSL/TLS。即不安全的 HTTP 協議加上 SSL/TLS 等於安全的 HTTPS。
網站首先花錢從權威 CA 機構那裏購買一個數字證書,證書通常包含一個私鑰和一個公鑰證書文件。瀏覽器訪問網站時將公鑰證書文件發送給瀏覽器,瀏覽器驗證收到的證書(權威機構擔保真假,主流瀏覽器和操作系統都會內置權威 CA 機構的根證書)如果證書可信,就隨機生成一個對稱加密密鑰 k,使用公鑰加密 k,得到密鑰 c。將密鑰 c 發送到網站,網站根據私鑰解密出密鑰 k,至此密鑰交換完成。這就是 HTTPS 加密傳輸的過程。
TCP頭標一共幾位?
20個字節160位。(面試的時候我說我記得是32比特的整數倍,大概128比特左右……)
具體定義如下代碼所示:
/*TCP頭定義,共20個字節*/
typedef struct _TCP_HEADER
{
short m_sSourPort; // 源端口號16bit
short m_sDestPort; // 目的端口號16bit
unsigned int m_uiSequNum; // 序列號32bit
unsigned int m_uiAcknowledgeNum; // 確認號32bit
short m_sHeaderLenAndFlag; // 前4位:TCP頭長度;中6位:保留;後6位:標誌位
short m_sWindowSize; // 窗口大小16bit
short m_sCheckSum; // 檢驗和16bit
short m_surgentPointer; // 緊急數據偏移量16bit
}__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
圖片來源看水印;
順帶一提,udp的頭短得多,只有8字節。
以上就是我的總結了,希望看到這裏的讀者點個小贊,或者評論區給我提出意見,讓我知道有人在看我的文章!這會是我更新的最大動力,謝謝!