TCP vs UDP 核心區別??
?題目?:TCP為什么稱為可靠傳輸協議?UDP在哪些場景下比TCP更具優勢?
?得分要點?:
-
?可靠性機制?
- 三握四揮建立可靠連接
- 確認應答(ACK)+ 超時重傳
- 滑動窗口流量控制
- 擁塞控制(慢啟動/AIMD)
-
?UDP優勢場景?
- ?低延遲優先?:實時音視頻(Zoom/RTC)、在線游戲(丟包影響<延遲影響)
- ?廣播/多播?:DHCP服務發現、IPTV流媒體
- ?簡單查詢?:DNS請求(通常使用UDP)、SNMP監控
?進階考點?:QUIC協議如何結合UDP實現可靠傳輸?
?解析方向?:QUIC在UDP之上實現自定義重傳/擁塞控制,整合TLS 1.3減少握手次數,解決隊頭阻塞問題。
??三次握手進階問題?
?題目?:如果第三次ACK丟失,TCP連接狀態會如何變化?系統會有怎樣的處理機制?
?問題拆解?:
- 服務端狀態變化:未收到ACK時維持SYN-RECEIVED狀態
- 服務端重傳:等待超時后重傳SYN-ACK包?(重試次數由
tcp_synack_retries
內核參數控制) - 客戶端行為:已進入ESTABLISHED,直接發送數據會觸發服務端RST復位
- 連接建立失敗判定條件:服務端超過最大重試次數后關閉半連接
?避坑指南?:需區分TCP實現細節(如Linux的SYN cookies
機制可防止SYN洪水攻擊,此時不會維持半連接狀態)。
?HTTPS加密流程?
?題目?:請描述從客戶端發起HTTPS請求到完成加密通信的全流程,重點說明RSA和AES分別在哪個階段使用。
?標準化回答模板?:
- ?TCP連接建立?:完成三次握手
- ?TLS握手階段?
- 客戶端發送
ClientHello
(包含支持的加密套件、隨機數) - 服務器回復
ServerHello
(選定套件)+ 證書(RSA公鑰)+?ServerRandom
- 客戶端驗證證書合法性,生成
PreMasterSecret
并用RSA公鑰加密傳輸 - 雙方通過PRF生成
MasterSecret
,推導出AES對稱會話密鑰?
- 客戶端發送
- ?加密數據傳輸?:應用層HTTP數據使用AES-GCM加密后傳輸
- ?連接關閉?:發送
close_notify
警報終止加密信道
?技術亮點?:強調前向保密(Forward Secrecy)的重要性。若使用ECDHE密鑰交換,即使服務器私鑰泄露,歷史會話仍安全。
基礎知識
以下為 ?加密算法分類與對比? 的大廠面試真題深度解析,結合騰訊、阿里、字節等高頻考點,覆蓋對稱加密、非對稱加密、哈希算法的核心知識點:
?一、HTTP狀態碼(面試必考)??
?1. 核心分類與常見狀態碼?
狀態碼范圍 | 類別 | 常見狀態碼及場景 | Android處理建議 |
---|---|---|---|
?1xx? | 信息響應 | 100 Continue(客戶端應繼續發送請求體) | 通常由框架自動處理,無需業務層干預 |
?2xx? | 成功響應 | ?200 OK?(標準成功) ?201 Created?(資源已創建,如POST成功) ?204 No Content?(成功但無返回體,如DELETE請求) | 檢查響應體格式(如JSON解析是否兼容空響應) |
?3xx? | 重定向 | ?301 Moved Permanently?(永久重定向) ?302 Found?(臨時重定向) ?304 Not Modified?(緩存有效,結合If-Modified-Since) | 處理重定向邏輯(如OkHttp默認自動跟進,可禁用:.followRedirects(false) ) |
?4xx? | 客戶端錯誤 | ?400 Bad Request?(請求格式錯誤) ?401 Unauthorized?(未認證) ?403 Forbidden?(無權限) ?404 Not Found?(資源不存在) | 彈窗提示用戶(如401跳轉登錄頁,404顯示錯誤頁) |
?5xx? | 服務端錯誤 | ?500 Internal Server Error?(服務器內部錯誤) ?502 Bad Gateway?(網關錯誤) ?503 Service Unavailable?(服務不可用,如超載或維護中) | 重試機制(指數退避) 降級策略(如展示緩存數據) |
?2. 面試高頻問題?
?問題?:503和504狀態碼有什么區別?如何處理?
?答?:
- ?503(服務不可用)??:服務器暫時過載或維護,客戶端應稍后重試。常見于秒殺活動或流量高峰。
- ?504(網關超時)??:服務器作為網關時,未及時從上游服務收到響應。可能因網絡問題或上游服務故障。
- ?處理策略?:
- 503:客戶端啟用退避重試(如首次1秒后重試,第二次3秒后)。
- 504:檢查網絡連接,若正常則提示用戶“服務響應超時”。
?問題?:304狀態碼是如何工作的?
?答?:
服務器通過對比請求頭中的If-Modified-Since
(時間戳)或If-None-Match
(ETag哈希)與資源最新版本,若未變化則返回304,客戶端使用本地緩存。在Android中可通過Cache-Control
和ETag
實現高效緩存,減少流量消耗。
?二、QUIC協議:基于UDP的下一代HTTP/3?
?1. 核心特性與優勢?
特性 | 說明 | 對移動端的優勢 |
---|---|---|
?基于UDP? | 繞過TCP協議棧,避免隊頭阻塞(Head-of-Line Blocking) | 弱網環境下(如高丟包)性能提升顯著 |
?0-RTT連接? | 首次連接1-RTT,后續會話可0-RTT(類似TCP Fast Open但更徹底) | 降低延遲,適合頻繁短連接場景(如推送通知) |
?多路復用? | 每個流(Stream)獨立傳輸,無需按序到達 | 頁面加載速度更快(如同時傳輸HTML/CSS/JS) |
?前向糾錯(FEC)?? | 添加冗余數據包,部分丟包時無需重傳 | 減少視頻卡頓,提升實時音畫質 |
?連接遷移? | 客戶端IP變化(如Wi-Fi切4G)時,連接保持可用 | 移動網絡切換不斷線 |
?2. QUIC在Android中的應用?
?庫與工具支持?:
- ?OkHttp?:實驗性支持(需啟用
okhttp-quic
模塊)。 - ?Cronet?(Chromium網絡庫):Android官方推薦,支持QUIC和HTTP/3。
?代碼示例(Cronet)??:
// 初始化Cronet引擎
val engine = CronetEngine.Builder(context).enableQuic(true).addQuicHint("example.com", 443, 443).build()// 發起QUIC請求
val request = engine.newUrlRequestBuilder("https://example.com/api/data",MyUrlRequestCallback(),executor
).build()
request.start()
?性能對比(QUIC vs TCP+TLS)??:
- ?連接建立時間?:QUIC 0-RTT比TCP+TLS 1.3的1-RTT快約30%。
- ?弱網吞吐量?:在20%丟包率下,QUIC比HTTP/2快2倍以上。
?3. 面試高頻問題?
?問題?:QUIC為什么選擇UDP而不是TCP?
?答?:
- ?避免TCP協議棧限制?:TCP由操作系統內核實現,修改困難;QUIC在用戶空間實現,迭代更快。
- ?解決隊頭阻塞?:TCP要求數據包按序到達,一個丟包會阻塞整個流;QUIC的流相互獨立,丟包只影響當前流。
?問題?:QUIC如何保證安全性?
?答?:
- ?強制加密?:所有QUIC數據包默認使用TLS 1.3加密,無法明文傳輸。
- ?連接標識符?:連接ID與IP解耦,防止IP偽造攻擊。
?問題?:在Android中如何優化QUIC的弱網表現?
?答?:
- ?前向糾錯(FEC)??:開啟FEC功能,容忍部分丟包。
- ?動態調整擁塞窗口?:根據網絡類型(Wi-Fi/4G)自動選擇算法(如BBR)。
- ?0-RTT會話恢復?:緩存會話憑證,網絡切換時快速恢復連接。
?三、真題場景:QUIC實戰優化??
?面試官?:你們在短視頻加載中如何應用QUIC?具體提升了哪些指標?
?答?:
我們在視頻預加載和首幀優化中引入了QUIC,核心策略有兩點:
- ?0-RTT連接復用?:用戶打開App時,提前與CDN建立QUIC會話,后續請求跳過握手,首幀時間從500ms降到200ms。
- ?多流并行傳輸?:視頻元數據、分片數據、封面圖通過不同QUIC流傳輸,即使某個流丟包,其他流不受影響,整體加載成功率從92%提升到98%。
?數據驗證?:
- ?弱網(30%丟包)??:QUIC比HTTP/2的卡頓率降低60%。
- ?連接遷移測試?:Wi-Fi切4G時,QUIC視頻續播成功率100%,TCP組為85%。
?真題一:HTTPS為何采用混合加密??
?問題?:HTTPS同時使用對稱加密和非對稱加密,為什么不直接用非對稱加密傳輸所有數據?
?答案拆解?:
-
?性能差異?:
- ?對稱加密(AES)??:加密速度極快(如AES-256加密1GB數據僅需約0.5秒),適合大量數據傳輸。
- ?非對稱加密(RSA)??:加密速度慢(RSA-2048加密同樣數據需約10分鐘),僅適合小數據(如密鑰交換)。
-
?密鑰管理難題?:
- 若僅用非對稱加密,每次傳輸需用公鑰加密數據,但公鑰可能被中間人替換(需依賴證書體系)。
- 混合加密中,非對稱加密僅用于傳輸對稱密鑰(如AES密鑰),后續通信由對稱加密完成,兼顧安全與效率。
?Android代碼示例?:
// 生成AES會話密鑰(實際由TLS協議自動完成)
KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES");
aesKeyGen.init(256);
SecretKey aesKey = aesKeyGen.generateKey();// 用RSA公鑰加密AES密鑰(模擬TLS握手過程)
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, serverPublicKey);
byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded());
?陷阱規避?:
- ?RSA填充模式?:必須使用OAEP(而非PKCS#1 v1.5),避免Bleichenbacher攻擊。
- ?密鑰長度?:RSA密鑰需≥2048位,否則易被暴力破解。
?真題二:為何推薦AES-GCM而非AES-CBC??
?問題?:在Android文件加密中,為何GCM模式比CBC更安全?如何避免GCM的IV重復問題?
?答案拆解?:
-
?GCM核心優勢?:
- ?AEAD模式?:同時提供加密和認證(Authenticated Encryption with Associated Data),無需額外計算HMAC。
- ?抗Padding Oracle攻擊?:CBC需要填充(如PKCS#7),攻擊者可利用填充錯誤獲取明文信息。
- ?并行計算?:GCM基于CTR模式,支持多核CPU加速(比CBC快30%+)。
-
?IV管理方案?:
- ?隨機生成IV?:每次加密生成12字節隨機IV(推薦),與密文一起存儲。
- ?計數器模式?:對大型文件分塊加密,使用遞增計數器(需全局唯一)。
// 生成隨機IV(Android最佳實踐) SecureRandom random = new SecureRandom(); byte[] iv = new byte[12]; random.nextBytes(iv); GCMParameterSpec spec = new GCMParameterSpec(128, iv); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
?延伸追問?:
- ?GCM的認證標簽(Authentication Tag)有何作用???
- 標簽長度通常為128位,用于驗證密文完整性和真實性,防止篡改。
- ?如何檢測IV是否重復???
- 使用全局計數器或數據庫記錄已用IV(適用于低頻操作),高并發場景推薦使用密碼學安全的隨機數生成器(如SecureRandom)。
?真題三:RSA與ECC在移動端的應用對比?
?問題?:為何TLS 1.3強制使用ECDHE密鑰交換,而不再支持RSA?這對Android應用有何影響?
?答案拆解?:
-
?前向安全性(Forward Secrecy)??:
- ?RSA密鑰交換?:無前向安全性,若服務器私鑰泄露,歷史通信可被解密。
- ?ECDHE(橢圓曲線DH)??:每次會話生成臨時密鑰,即使私鑰泄露,歷史會話仍安全。
-
?性能與資源占用?:
- ?ECC密鑰長度?:256位ECC ≈ 3072位RSA安全性,但計算速度快3倍,內存占用減少60%。
- ?握手速度?:ECDHE在移動端完成握手僅需100ms(RSA需300ms+)。
?Android代碼示例(生成ECC密鑰對)??:
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "AndroidKeyStore"
);
keyPairGenerator.initialize(new KeyGenParameterSpec.Builder("ecc_key",KeyProperties.PURPOSE_AGREE_KEY // 密鑰協商用途
).setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")).setDigests(KeyProperties.DIGEST_SHA256).build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
?陷阱規避?:
- ?曲線選擇?:避免使用NIST未標準化的曲線(如secp192k1),推薦secp256r1或X25519。
- ?Android版本兼容?:ECDHE在Android 4.3(API 18)及以上支持,需兼容舊版本時回退到RSA。
?真題四:SHA-256替代MD5的必然性?
?問題?:為何Android P之后禁止MD5在TLS中使用?如何安全替換遺留系統中的MD5?
?答案拆解?:
-
?碰撞攻擊風險?:
- ?MD5?:2004年王小云團隊攻破,可在1小時內構造碰撞(相同哈希的不同文件)。
- ?SHA-256?:理論碰撞概率為1/(2^128),現有算力無法在合理時間內破解。
-
?遷移方案?:
- ?代碼層替換?:
// 廢棄代碼 MessageDigest md = MessageDigest.getInstance("MD5");// 修復代碼 MessageDigest md = MessageDigest.getInstance("SHA-256");
- ?數據遷移?:
- 對已存儲的MD5哈希值,要求用戶重新輸入密碼并用SHA-256+鹽值重新哈希。
- 使用漸進式遷移策略:新用戶用SHA-256,舊用戶登錄時強制升級。
- ?代碼層替換?:
?延伸追問?:
- ?HMAC-MD5是否安全???
- 若密鑰保密,HMAC-MD5仍可用(但Android P+會警告),推薦升級到HMAC-SHA256。
- ?如何檢測代碼中的MD5使用???
- 使用Android Studio的Lint工具掃描
MessageDigest.getInstance("MD5")
,或SonarQube靜態分析。
- 使用Android Studio的Lint工具掃描
?真題五:Android密鑰存儲的漏洞與防護??
?問題?:如何防止Root后的設備提取Android Keystore中的密鑰?
?答案拆解?:
-
?硬件級防護?:
- ?TEE(可信執行環境)??:密鑰生成、存儲、使用均在安全世界(Secure World)完成,普通進程無法訪問。
- ?StrongBox?:Android 9.0+支持獨立安全芯片(如Google Titan M),密鑰永不離開芯片。
-
?代碼級防護?:
- ?生物認證綁定?:
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder("aes_key",KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT ).setUserAuthenticationRequired(true).setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG).build();
- ?密鑰有效期?:設置
setUserAuthenticationValidityDurationSeconds(300)
,超時后需重新驗證。
- ?生物認證綁定?:
?陷阱規避?:
- ?禁止密鑰導出?:生成時設置
setIsStrongBoxBacked(true)
(若設備支持),并禁用setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
。 - ?防暴力破解?:使用
setInvalidatedByBiometricEnrollment(true)
,生物信息變更后密鑰自動失效。
面試話題回答
?面試官?:嗨,我看你簡歷里提到熟悉網絡通信原理,能簡單聊聊TCP的三次握手嗎?比如為什么需要三次而不是兩次?
?你?:
啊,這個問題我之前學習的時候也糾結過。打個比方吧,就像兩個人打電話確認彼此都能聽見。假設客戶端是A,服務器是B:
- 第一次A打給B說“喂,能聽到嗎?”(SYN)
- B聽到后回“我能聽到,你聽得到我嗎?”(SYN-ACK)
- 這時候如果只有兩次,A可能沒聽到B的回復就直接開始說話了,結果B根本沒收到后續內容。所以A必須再回一句“嗯,我也能聽到你”(ACK),這樣雙方才確定連接是雙向通暢的。
其實三次主要是為了防止歷史連接的混亂。比如A之前發過一個舊的SYN請求,如果只用兩次握手,B收到舊請求就直接建立連接,但A已經不認這個連接了,這時候B就會傻等…(笑)
?面試官?:有意思的比喻。那實際開發中,Android應用怎么確保網絡請求的安全性呢?比如用HTTP還是HTTPS?
?你?:
啊,這個問題我踩過坑!之前自己寫Demo圖方便用了HTTP,結果發現抓包工具隨便看請求內容,嚇得趕緊改HTTPS。現在如果是正式項目,肯定全走HTTPS的。不過具體實施的時候要注意幾點:
- ?證書校驗?:比如用OkHttp的時候得設置
CertificatePinner
,防止中間人攻擊。之前我測試時發現某些廠商手機會自己裝證書,不配置的話HTTPS也可能被破解。 - ?加密套件選擇?:服務器得支持TLS 1.2以上,像我們學校的老系統還用TLS 1.0,用
nscurl
檢查直接被判定不安全。 - ?敏感數據防護?:就算用了HTTPS,密碼之類的也不能明文傳,得客戶端加鹽哈希再傳輸。對了,像Retrofit的
@Body
配合GSON會自動處理序列化,但要注意不要泄露日志里的請求體…
?面試官?:說到Retrofit,如果讓你設計一個圖片加載模塊,怎么平衡流暢度和流量消耗?
?你?:
這個場景我覺得得分層考慮。比如:
- ?緩存策略?:優先用內存緩存(LruCache),快速響應滾動。然后磁盤緩存存處理過的圖片,像Glide會在本地存不同尺寸的副本。我之前嘗試過用
OkHttp的CacheInterceptor
,但發現文件緩存需要自己控制過期時間。 - ?網絡優化?:根據網絡類型調整圖片質量。比如Wi-Fi下加載原圖,移動網絡用WebP格式壓縮。甚至可以在請求頭里帶
Save-Data: on
讓CDN返回低分辨率圖。 - ?懶加載和預加載?:RecyclerView滑動時不加載,停頓時再觸發。像ViewPager可以預加載相鄰頁的圖片,不過得注意內存壓力。
對了,之前我用Coil庫發現它默認會根據ImageView大小下載合適尺寸的圖,這個設計對流量節省挺有幫助的!
?面試官?:如果現在有個需求:實現APP內的長連接消息推送,你會考慮哪些技術方案?
?你?:
長連接啊…這塊我還沒實際做過,但根據我查的資料,大概有幾種思路:
- ?WebSocket?:比如用OkHttp的WebSocket支持,自己維護心跳包。優點是控制靈活,但得處理重連和保活,可能會比較耗電。
- ?Firebase Cloud Messaging(FCM)??:如果是海外項目可以直接用,國內可能需要搭配廠商推送(小米、華為的SDK),但集成起來有點瑣碎。
- ?MQTT協議?:聽說適合物聯網場景,輕量級。不過得自己搭服務器,像用EMQX這種開源方案。
不管用哪種,我覺得都要考慮:
- ?保活機制?:Android系統后臺會限制網絡請求,可能需要用Foreground Service或者JobScheduler定期喚醒。
- ?消息可靠性?:比如離線消息存儲,重發確認機制。對了,微信的推送好像走的是長連接+智能心跳,他們的技術博客提到過根據網絡狀態調整心跳間隔…
好的!以下是一個 ?模擬Android實習生面試對話模塊? ,用更自然的口語化表達還原真實面試場景,幫助你感受如何將知識點融入實際對話:
?場景一:技術基礎考察?
?面試官?:看你簡歷里提到了加密算法在Android中的應用,能簡單說說HTTPS握手過程中對稱加密和非對稱加密是怎么配合的嗎?
?你?:
嗯,好的。HTTPS握手其實是一個混合加密的過程。剛開始的時候,客戶端和服務器會先用非對稱加密(比如RSA或者ECC)來安全地交換一個對稱加密的密鑰。比如客戶端生成一個隨機的AES密鑰,然后用服務器的公鑰加密這個密鑰傳給服務器,服務器用自己的私鑰解密拿到這個AES密鑰。這樣一來,后續的實際數據傳輸就可以用AES這種對稱加密算法了,因為它速度更快,適合處理大量數據。整個過程有點像“先用保險箱寄鑰匙,再用鑰匙開鎖運貨”。
?面試官追問?:為什么RSA只用來傳密鑰,而不是直接加密所有數據?
?你?:
因為RSA這類非對稱加密算法計算量太大了。比如加密一段1MB的數據,RSA可能要花幾秒鐘,而AES可能只要幾毫秒。所以為了性能和效率,實際數據用對稱加密更合適。非對稱加密就像快遞員送鑰匙,雖然安全但成本高,不能天天用;對稱加密才是真正搬家的卡車,又快又能裝。
?場景二:實戰場景分析?
?面試官?:假設你需要在Android里加密本地存儲的用戶登錄密碼,你會怎么設計?有沒有遇到過什么坑?
?你?:
如果是加密密碼的話,首先絕對不能用明文存,也不能直接用MD5這種簡單的哈希。我之前在項目里用的是PBKDF2 + 鹽值的方式。具體來說,用戶輸入密碼后,我會生成一個隨機鹽值(比如16字節),然后用PBKDF2算法把密碼和鹽值混合起來,迭代個幾萬次(比如10萬次),生成一個密鑰。最后把這個鹽值和哈希結果一起存到本地。這樣即使數據庫泄露,攻擊者也沒法直接用彩虹表破解。
不過實際開發的時候,我遇到過一個坑:一開始沒處理好鹽值的隨機性,用了系統時間生成鹽值,結果發現不同用戶的鹽值可能會重復。后來改用了SecureRandom
類生成真隨機數才解決這個問題。
?場景三:開放性問題?
?面試官?:如果現在要你優化一個Android App的網絡請求安全性,除了HTTPS,你還會考慮哪些點?
?你?:
除了HTTPS,我覺得還有幾個方向可以優化。
第一是證書固定(SSL Pinning)?,比如用OkHttp的CertificatePinner
把服務器證書的公鑰哈希值寫死在客戶端,防止中間人攻擊。
第二是雙向認證(mTLS)?,比如讓客戶端也帶證書,適合金融類App的高安全場景。
第三是敏感數據二次加密,比如即使走了HTTPS,用戶的身份證號、銀行卡號這類數據,可以用AES-GCM在業務層再加密一次。
最后還要注意降級攻擊防護,比如在Network Security Config
里禁用低版本的TLS,強制只用TLS 1.2+。
?場景四:原理深挖?
?面試官?:你剛才提到AES-GCM比CBC更安全,能具體說說為什么嗎?
?你?:
當然!CBC模式有一個問題叫“填充預言攻擊”(Padding Oracle Attack)。簡單來說,攻擊者可以通過不斷發送篡改過的密文,根據服務器的錯誤提示(比如返回“解密失敗”還是“解密成功但數據無效”)來猜出明文內容。而GCM模式屬于“認證加密”(AEAD),它在加密的同時會生成一個認證標簽(Authentication Tag),解密時先驗證這個標簽,如果數據被篡改就直接拒絕,不會泄露任何信息。
另外,GCM不需要填充數據,所以天然避免了填充相關的漏洞,而且還能并行計算,性能更好,相當于既安全又省油。
?場景五:學習能力考察?
?面試官?:如果現在要你學習一個陌生的加密算法(比如國密SM4),你會怎么快速上手?
?你?:
首先我會查官方文檔或者RFC標準,了解它的設計原理、密鑰長度、使用場景這些基本信息。
然后找開源庫的Android實現,比如Bouncy Castle或者Conscrypt,看看它們的API文檔和示例代碼。
接著我會寫個小Demo,比如用SM4加密一個字符串,對比加密前后的結果是否符合預期。
如果遇到問題,我會去GitHub上看Issues或者Stack Overflow,看看別人是怎么解決的。
最后,我可能會在本地寫單元測試,模擬各種邊界情況(比如空數據、超長數據),確保算法的穩定性和兼容性。?
?場景一:DNS解析流程與優化?
?面試官?:用戶在瀏覽器輸入https://www.example.com
,到最終建立連接,DNS解析經歷了哪些步驟?你們在項目中如何優化這一過程?
?你?:
當用戶輸入網址后,系統會先檢查本地緩存,比如瀏覽器和操作系統的DNS緩存,如果有記錄就直接用。如果沒找到,就會向本地DNS服務器(比如運營商提供的)發起查詢。本地DNS會從根域名服務器開始,一步步找到負責.com
的頂級域名服務器,再找到example.com
的權威服務器,最終拿到IP地址。這個過程默認用UDP協議,因為速度快,適合小數據包。
在項目里,我們優化DNS解析主要是通過預解析和緩存策略。比如在App啟動時,提前解析核心域名(像API的域名),減少用戶首次請求的等待時間。另外,我們用了OkHttp的DNS緩存功能,設置合理的TTL(比如5分鐘),避免重復查詢。對于弱網環境,還接入了HTTPDNS服務,繞過運營商DNS,直接通過HTTP請求權威服務器,這樣既防劫持又提升了解析速度。
?面試官追問?:如果遇到DNS劫持,你們是怎么檢測的?
?你?:
我們會在關鍵業務場景(比如登錄、支付)做雙校驗。首先,客戶端解析域名拿到IP后,會通過另一個通道(比如用阿里云的HTTPDNS服務)再解析一次,對比兩個IP是否一致。如果不一致,就觸發告警,提示用戶網絡可能不安全。同時,在HTTPS握手時啟用證書固定(Certificate Pinning),這樣即使DNS被劫持,偽造的服務器證書也無法通過校驗,連接會被直接終止。
?場景二:TCP滑動窗口與性能優化??
?面試官?:TCP的滑動窗口機制對移動端網絡性能有什么影響?在Android開發中如何利用這一點優化請求速度?
?你?:
滑動窗口的核心是讓發送方可以連續發多個數據包,而不用等每個包的確認,這樣能充分利用帶寬。比如窗口大小是3000字節,發送方可以一口氣發3個1000字節的包,接收方確認后再繼續發。這對移動端來說特別重要,因為網絡波動大,減少等待時間能明顯提升速度。
在Android里,我們通過OkHttp的配置來優化。比如調整connectionSpecs
,啟用TCP快速打開(Fast Open),減少握手次數。另外,在弱網環境下,我們動態調整超時時間——如果發現連續丟包,就縮小窗口大小,避免擁塞;網絡恢復后再逐步擴大窗口。實際測試下來,下載大文件的平均速度提升了20%左右。
?面試官追問?:如果滑動窗口的尺寸設置不合理,會導致什么問題?
?你?:
窗口太小的話,發送方總是要等確認,帶寬利用率低,用戶會覺得網速慢;窗口太大,一旦網絡突然變差(比如進電梯),大量數據包堆積在中間節點,可能引發嚴重丟包,反而更慢。我們的做法是根據網絡類型動態調整——Wi-Fi下窗口調大,4G適中,2G或弱信號時縮小,同時結合TCP的擁塞控制算法(比如BBR),盡量平衡速度和穩定性。
?場景三:DNS劫持防護實戰?
?面試官?:你們在App里是如何防止DNS劫持的?有沒有遇到過什么棘手的案例?
?你?:
防DNS劫持我們用了三招:?HTTPS+證書固定、HTTPDNS、雙解析校驗。比如在支付環節,所有請求都強制走HTTPS,并且證書固定到幾個特定的公鑰哈希,這樣即使DNS被黑,偽造的服務器也無法通過證書驗證。同時接入了騰訊云的HTTPDNS服務,繞過本地DNS,直接從權威服務器獲取IP,避免運營商劫持。
之前遇到過一個棘手問題:某個地區運營商的DNS會把無法解析的域名指向廣告頁面。我們當時的登錄接口剛好用了第三方域名,被劫持后用戶根本打不開登錄頁。臨時方案是在客戶端加入域名解析白名單,只有解析到指定IP才允許連接;長期方案是全面接入HTTPDNS,并且在后端做IP合法性校驗,確保只有授權的服務器能響應。
?面試官追問?:如果用戶設備本身被黑了(比如hosts文件被篡改),你們怎么應對?
?你?:
這種情況我們會在App啟動時做一次本地hosts文件掃描。比如檢查/system/etc/hosts
里是否有異常域名映射(像把淘寶域名指向陌生IP),如果發現就彈窗警告用戶設備可能中毒。另外,關鍵業務接口不再依賴域名,改用IP直連+動態域名更新機制,后臺定期下發最新的IP列表,即使hosts被改,也能通過IP直接連接正版服務器。
?場景四:加密協議與Android安全?
?面試官?:為什么現在推薦用TLS 1.3?在Android里怎么保證低版本系統的兼容性?
?你?:
TLS 1.3主要兩點優勢:?更快和更安全。它簡化了握手過程,從原來的兩次往返(2-RTT)變成一次(1-RTT),甚至零往返(0-RTT),連接速度提升明顯。而且刪除了不安全的加密算法(比如RC4、SHA-1),強制使用前向保密的密鑰交換(比如ECDHE),即使私鑰泄露,之前的通信記錄也無法解密。
對于低版本Android(比如4.x),我們用的是OkHttp的兼容模式,通過ConnectionSpec.COMPATIBLE_TLS
配置,支持TLS 1.2和1.3的協商。同時,在自定義SSLContext時,明確指定支持的協議版本,禁用老舊版本
val sslContext = SSLContext.getInstance("TLSv1.3")
sslContext.init(null, trustManagers, null)
val sslSocketFactory = sslContext.socketFactoryval client = OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager).connectionSpecs(listOf(ConnectionSpec.MODERN_TLS)) // 強制TLS 1.3或1.2.build()
這樣即使系統本身不支持TLS 1.3,OkHttp也會通過Conscrypt庫提供兼容支持,確保高版本協議可用。
?場景五:網絡層安全與用戶體驗平衡?
?面試官?:在加強網絡安全的過程中,你們是怎么平衡用戶體驗的?比如嚴格校驗是否會影響請求速度?
?你?:
安全性和性能確實需要權衡。我們的原則是關鍵業務嚴格校驗,非關鍵業務適度放寬。比如支付流程會做四重校驗:DNS雙解析、證書固定、報文簽名、雙向認證;而普通的圖片加載只用HTTPS基礎校驗,避免過度消耗資源。
另外,我們會把部分校驗邏輯后移到初始化階段。比如App啟動時預取證書、預加載DNS解析結果,這樣用戶實際操作時不會感覺到延遲。對于證書校驗這種CPU密集型操作,還用了Native層優化(比如C++實現RSA驗簽),比純Java快3倍以上,用戶完全無感知。
Android學習總結之網絡加密算法篇_android 常用加密-CSDN博客https://blog.csdn.net/2301_80329517/article/details/147469248?Android第三次面試總結(網絡篇)_android網絡架構精講-CSDN博客
https://blog.csdn.net/2301_80329517/article/details/146324518