“本文大約有 2794 字。
面試筆記系列的第 2 篇文章。
01|面試題來源
-
老虎二面
-
BIGO 一面
02|概念題
1. C++ 的內存管理?
在 C++ 中,內存分爲 5 個區:堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區。
堆/棧、malloc/new
2. TCP 和 UDP 的區別?
TCP 是面向連接的,UDP 是面向無連接的。
-
TCP 提供可靠交付。UDP 繼承了 IP 包的特性,不保證不丟失,不保證按順序到達。
-
TCP 是面向字節流的,發送的時候發的是一個流,沒頭沒尾。UDP 是基於數據報的,一個一個的發,一個一個的收。
-
TCP 是可以有擁塞控制的。它意識到包丟棄了或者網絡的環境不好了,就會根據情況調整自己的行爲,看看是不是發快了,要不要發慢點。UDP 就不回,應用讓他發,它就發,可不管網絡情況怎麼樣。
-
TCP 是一個有狀態服務,精確地記着發送了沒有,接收到沒有,發送到哪個了,應該接收哪個了,錯一點兒都不行。UDP 則是無狀態服務,沒有什麼保證機制,一個包發出去就發出去了。
3. TCP 怎麼確定可靠傳輸?
-
順序問題,穩重不亂;
每一個包都有一個 ID。在建立連接的時候,會商定起始的 ID 是什麼,然後按照 ID 一個個發送。
-
丟包問題,承諾靠譜;
對於發送的包都要進行應答,有高效的累計確認。
-
連接維護,有始有終;
-
流量控制,把握分寸;
接收窗口控制發送窗口。當發送端的窗口爲 0 時(接收方一直不處理數據),發送方會定時發送窗口探測數據包,看看是否有機會調整窗口大小。
-
擁塞控制,知進知退。
避免包丟失和超時重傳,指數式增長、線性增長,快速重傳算法:cwnd 減半爲 cwnd/2,然後 sshthresh = cwnd。
4. 流量控制與擁塞控制
流量控制機制,在對於包的確認中,同時會攜帶一個窗口的大小。包的確認到達的時候,窗口滑動,纔有更多的包可以發送。
如果接收方處理的太慢,導致緩存中沒有空間了,可以通過確認信息修改窗口大小,降低發送方發送速度或者發送方暫停發送。
發送方會定時發送窗口探測數據包,看是否有機會調整窗口的大小。又要防止低能窗口綜合徵,別空出一個字節來就告訴發送方,有馬上填滿了,具備一定的鬆弛操作,直到到達一定的大小,才更新窗口。
“粘包”其實是應用程序中沒有處理好數據包分割,兩個應用層的數據包粘在一塊了,這不關 TCP 的事,在大學學習網絡的時候,書本上就沒有這個名詞。
擁塞控制:TCP 的擁塞控制主要來避免兩種現象,即包丟失和超時重傳。一旦出現了這些現象就說明,發送的速度太快了,要慢一些。
一條 TCP 連接開始,cwnd 設置爲一個報文段,一次只能發送一個;當收到這一個確認的時候,cwnd 加一,於是一次能夠發送兩個;當這兩個的確認到來的時候,每個確認 cwnd 加一,兩個確認 cwnd 加二,於是一次能夠發送四個;當這四個的確認到來的時候,每個確認 cwnd 加一,四個確認 cwnd 加四,於是一次能夠發送八個。可以看出這是指數性的增長。
漲到什麼時候是個頭呢?有一個值叫做門限(ssthresh)爲 65535 個字節,當超過這個值的時候,就要小心一點了,就不能增長那麼快了。
於是,每收到一個確認後,cwnd 增加 1/cwnd,我們接着上面的過程來,一次發送八個,當八個確認到來的時候,每個確認增加 1/8,八個確認一共 cwnd 增加 1,於是一次能夠發送九個,變成了線性增長。
但是線性增長還是增長,還是越來越多,直到發送擁塞。擁塞的一種表現形式是丟包,需要超時重傳。
有一種方式是,將 sshresh 設爲 cwnd/2,將 cwnd 設爲 1,重新開始慢啓動。。但是這種方式太激進了,將一個高速的傳輸速度一下子停了下來,會造成網絡卡頓。
快速重傳算法。當接收端發現丟了一箇中間包的時候,發送三次前一個包的 ACK,於是發送端就會快速的重傳,不必等待超時再重傳。TCP 認爲這種情況不嚴重,因爲大部分沒丟,只丟了一小部分,cwnd 減半爲 cwnd/2,然後 sshthresh = cwnd,呈線性增長。
TCP BBR 擁塞算法,它佔滿帶寬,但是不佔滿緩存,時延較低。
03|算法題
1. 怎麼刪除鏈表第 n 個結點?
(1)找到待刪節點的前一個節點,然後指向待刪節點的下一個節點,釋放待刪節點的空間。
(2)如果傳入的參數爲第 n 個節點,則可以直接將後一個節點值覆蓋掉當前節點,然後刪除後一節點。注:傳入的節點不是最後一個節點。
04|理解應用題
1. STL 容器是線程安全的還是不安全的?
多線程讀取是安全的,多線程對不同的容器寫是安全的。多個線程可以讀同一個容器內的數據,讀時不允許寫操作。
2. Windows 出現了內存泄漏怎麼辦?
* VC++ 的 CRT 庫在 Debug 下支持內存的診斷。
* IBM 的 Purify 號稱最強大的內存檢測工具。
3. TCP, UDP 應用的場景
TCP 支持的應用層協議主要有:Telnet、FTP、SMTP、HTTP。
UDP 支持的應用層協議有:DNS、NFS(網絡文件系統)、SNMP(簡單的網絡管理協議)、TFTP(通用文件傳輸協議)等。
UDP 的三大應用場景:
第一,需要資源少,在網絡情況比較好的內網,或者對於丟包不敏感的應用。
第二,不需要一對一溝通,建立連接,而是可以廣播的應用。第三,需要處理速度快,時延低,可以容忍少數丟包,但是要求即便網絡擁塞,也毫不退縮,一往無前的時候。
基於 UDP 的五個例子:
(1)網頁訪問:QUIC(全稱Quick UDP Internet Connections,快速 UDP 互聯網連接)是 Google 提出的一種基於 UDP 改進的通信協議。QUIC 在應用層上,會自己實現快速連接建立、減少重傳時延,自適應擁塞控制。
(2)流媒體的協議
很多直播應用,都基於 UDP 實現了自己的視頻傳輸協議。直播,實時性比較比較重要,寧可丟包,也不要卡頓的。在網絡不好的情況下,應用希望選擇性的丟幀。
老的視頻幀丟了其實也就丟了,就算再傳過來用戶也不在意了,他們要看新的了,如果老是沒來就等着,卡頓了,新的也看不了,那就會丟失客戶。
(3)實時遊戲
遊戲有一個特點,就是實時性比較高。TCP 的強順序問題,如果出現一個數據包丟失,容易造成卡頓。遊戲對實時要求較爲嚴格的情況下,採用自定義的可靠 UDP 協議,自定義重傳策略,能夠把丟包產生的延遲降到最低,儘量減少網絡問題對遊戲性造成的影響。
(4)IoT 物聯網
物聯網領域終端資源少,很可能只是個內存非常小的嵌入式系統,而維護 TCP 協議代價太大;另一方面,物聯網對實時性要求也很高,而 TCP 還是因爲上面的那些原因導致時延大。
Google 推出的物聯網通信協議 Thread,就是基於 UDP 協議的。
在 4G 網絡裏,移動流量上網的數據面對的協議 GTP-U 是基於 UDP 的。
4. 紅黑樹
這裏我寫了一篇博客,講的是紅黑樹與 2-3樹的等價性,請看參考。
5. 穩定的排序算法
穩定性:*穩定排序算法*會讓原本有相等鍵值的記錄維持相對次序,原本在前面的還是在前面。
穩定的排序:冒泡、插入、桶子、計數、歸併、基數。
“快”“堆”“選”“希“不穩。
快:2330 ==> 切分 i 和 j 互換,3 和 0 換。
堆:222 === > 第一個出堆後,選擇後面的一個放到堆頂。
選擇:221 ==> 122 一趟排序後,第一個 2 個最後一個 1 換了位置。
希爾明顯不穩。
6. C++ 有哪些創建線程的方法?
(Function Pointer)函數指針
(Function Objects)函數對象
(Lambda functions)
生產者消費者,傳遞的是函數指針。
05|參考
1. 數據結構 | 2-3樹與紅黑樹的等價性
https://donngdev.github.io/posts/rb-tree
2. Have Fun with LeetCode
https://github.com/donngdev/Have-Fun-with-LeetCode
PS:關注微信公衆號「藍本本」,和我一起學習、進修和放縱好奇心。
題圖:Photo by Mohamed Khaled from Pexels.
Landon
——
學習、進修和放縱好奇心!
@ 藍本本
——