Alamofire初探
Alamofire初探一. Alamofire概述二. URLSesstion基礎(chǔ)三、TCP的三次握手四、TCP數(shù)據(jù)的傳輸過程五、TCP的四次揮手一. Alamofire概述對于使用Objective-C的開發(fā)者一定非常熟悉AFNetworking這個網(wǎng)絡(luò)框架。在蘋果推出的Swift之后AFNetworking的作者專門用Swift來編寫一個類似AFNetworking的網(wǎng)絡(luò)框架稱為Alamofire。Alamofire地址因為Alamofire是對蘋果URLSesstion的封裝,所以先來了解下URLSesstion的基礎(chǔ)二. URLSesstion基礎(chǔ)URLSession.shared.dataTask(with: url) { (data, response, error) in if error nil { print(請求成功\(String(describing: response)) ) } }.resume()此過程省略了一個重要的東西URLSessionConfigurationopen class var default: URLSessionConfiguration { get } open class var ephemeral: URLSessionConfiguration { get } available(iOS 8.0, *) open class func background(withIdentifier identifier: String) - URLSessionConfigurationURLSessionConfiguration有三種模式default默認(rèn)模式通常使用這種模式就夠了default模式下系統(tǒng)會創(chuàng)建一個持久化的緩存并在用戶的鑰匙串中存儲證書ephemeral:系統(tǒng)沒有任何持久性存儲所有內(nèi)容的生命周期與session相同當(dāng)session無效時所有內(nèi)容自動釋放let configuration1 URLSessionConfiguration.default let configuration2 URLSessionConfiguration.ephemeral print(沙盒大小: \(String(describing: configuration1.urlCache?.diskCapacity))) print(內(nèi)存大小: \(String(describing: configuration1.urlCache?.memoryCapacity))) print(沙盒大小: \(String(describing: configuration2.urlCache?.diskCapacity))) print(內(nèi)存大小: \(String(describing: configuration2.urlCache?.memoryCapacity)))background創(chuàng)建一個可以在后臺甚至app已經(jīng)關(guān)閉的時候仍然在傳輸數(shù)據(jù)的會話。background模式可以在程序掛起退出崩潰的情況下運行task.也可以利用標(biāo)識符來進(jìn)行恢復(fù)。注意后臺session一定要在創(chuàng)建的時候賦予一個唯一的identifier,這樣在app下次運行的時候能夠根據(jù)identifier來進(jìn)行相關(guān)的區(qū)分如果用戶關(guān)閉了app,ios系統(tǒng)會關(guān)閉所有的background Session.而且被用戶強制關(guān)閉了以后iOS系統(tǒng)不回主動喚醒app,只有用戶下次啟動了app,數(shù)據(jù)傳輸才會繼續(xù)let configuration URLSessionConfiguration.background(withIdentifier: self.createID()) let session URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main) session.downloadTask(with: url).resume()session代理extension ViewController:URLSessionDownloadDelegate{ func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { // 下載完成 - 開始沙盒遷移 print(下載完成 - \(location)) let locationPath location.path //拷貝到用戶目錄文件名以時間戳命名 let documnets NSHomeDirectory() /Documents/ self.lgCurrentDataTurnString() .mp4 print(移動地址:\(documnets)) //創(chuàng)建文件管理器 let fileManager FileManager.default try! fileManager.moveItem(atPath: locationPath, toPath: documnets) } func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { print( bytesWritten \(bytesWritten)\n totalBytesWritten \(totalBytesWritten)\n totalBytesExpectedToWrite \(totalBytesExpectedToWrite)) print(下載進(jìn)度: \(Double(totalBytesWritten)/Double(totalBytesExpectedToWrite))\n) } }注意上面的設(shè)置還是不能達(dá)到后臺下載還需要設(shè)置下面2步開啟后臺下載權(quán)限 (The completion handler to call when you finish processing the events. Calling this completion handler lets the system know that your app’s user interface is updated and a new snapshot can be taken.)用于保存后臺下載的completionHandler var backgroundSessionCompletionHandler: (() - Void)? func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: escaping () - Void) { self.backgroundSessionCompletionHandler completionHandler }回調(diào)系統(tǒng)回調(diào)告訴系統(tǒng)及時更新屏幕func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { print(后臺任務(wù)下載回來) DispatchQueue.main.async { guard let appDelegate UIApplication.shared.delegate as? AppDelegate, let backgroundHandle appDelegate.backgroundSessionCompletionHandler else { return } backgroundHandle() } }三、TCP的三次握手http請求是基于tcp連接的tcp有6種表示位SYN(synchronous建立聯(lián)機)ACK(acknowledgement確認(rèn))PSH(push傳送)FIN(finish結(jié)束)RST(reset重置)URG(urgent緊急)sequence number(順序號碼)acknowledge number(確認(rèn)號碼)客戶端向服務(wù)器發(fā)出連接請求報文這時報文首部中的同部位SYN1,同時隨機生成初始序列號seqx,此時TCP客戶端進(jìn)程進(jìn)入了SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定SYN報文段(SYN1的報文段)不能攜帶數(shù)據(jù)但需要消耗掉一個序號。這個三次握手中的開始表示客戶端想要和服務(wù)端建立連接。TCP服務(wù)器收到請求報文后如果同意連接則發(fā)出確認(rèn)報文確認(rèn)報文中應(yīng)該ACK1,SYN1,確認(rèn)號是ackx1,同時也要自己隨機初始化一個序列號seqy,此時TCP服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD(同步收到)狀態(tài)這個報文也不能攜帶數(shù)據(jù)但是同樣要消耗一個序號。這個報文帶有SYN(建立連接)和ACK(確認(rèn))標(biāo)志詢問客戶端是否準(zhǔn)備好。TCP客戶進(jìn)程收到確認(rèn)后還要向服務(wù)器給出確認(rèn)。確認(rèn)報文的ACK1,acky1,此時TCP連接建立客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)TCP規(guī)定ACK報文段可以攜帶數(shù)據(jù)但是如果不攜帶數(shù)據(jù)則不消耗序號這里客戶端表示我已經(jīng)準(zhǔn)備好。為什么要三次握手呢舉例已失效的連接請求報文段客戶端發(fā)送了第一個連接的請求報文但由于網(wǎng)絡(luò)不好這個請求沒有立即到達(dá)服務(wù)端而是在某個網(wǎng)絡(luò)節(jié)點中滯留了直到某個時間才到達(dá)server本來這已經(jīng)是一個失效的報文但是server端收到這個請求報文后還是會像客戶端發(fā)送確認(rèn)的報文,表示同意連接。假如不采用三次握手那么server發(fā)出確認(rèn)后新的建立就連接了但其實這個請求是失效的請求客戶端是不會理睬server端的確認(rèn)信息的也不會像服務(wù)端發(fā)送確認(rèn)的請求,但是server認(rèn)為新的連接已經(jīng)建立起來了并一直等待客戶端發(fā)來的數(shù)據(jù)這樣server端很多資源都白白浪費掉了采用三次握手就是為了防止這種情況的發(fā)生server會因為收不到確認(rèn)的報文就知道客戶端并沒有建立連接這就是三次握手的作用。四、TCP數(shù)據(jù)的傳輸過程建立連接后兩臺主機就可以相互傳輸數(shù)據(jù)了。如下圖所示主機A初始seq為1200,滑動窗體為100,向主機B傳遞數(shù)據(jù)的過程。假設(shè)主機B在完全成功接收數(shù)據(jù)的基礎(chǔ)上,那么主機B為了確認(rèn)這一點向主機A發(fā)送 ACK 包并將 Ack 號設(shè)置為 1301。因此按如下的公式確認(rèn) Ack 號Ack號 Seq號 傳遞的字節(jié)數(shù) 1 這是在完全接受成功的情況下主機A獲得B傳來的ack(1301)后,開始發(fā)送seq為1301,滑動窗體為100的數(shù)據(jù)?!c三次握手協(xié)議相同最后加 1 是為了告訴對方要傳遞的 Seq 號。上面說了主機B完全成功接收A發(fā)來的數(shù)據(jù)才是這樣的,如果存在丟包該如何下面分析傳輸過程中數(shù)據(jù)包丟失的情況如下圖所示上圖表示通過 Seq 1301 數(shù)據(jù)包向主機B傳遞100字節(jié)的數(shù)據(jù)但中間發(fā)生了錯誤主機B未收到。經(jīng)過一段時間后主機A仍未收到對于 Seq 1301 的ACK確認(rèn)因此嘗試重傳數(shù)據(jù)。為了完成數(shù)據(jù)包的重傳TCP套接字每次發(fā)送數(shù)據(jù)包時都會啟動定時器如果在一定時間內(nèi)沒有收到目標(biāo)機器傳回的 ACK 包那么定時器超時數(shù)據(jù)包會重傳。五、TCP的四次揮手TCP發(fā)送一個FIN(結(jié)束)用來關(guān)閉客戶端到服務(wù)端的連接客戶端進(jìn)程發(fā)出連接釋放報文并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報文首部FIN1,其序列號為sequ(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個字節(jié)的序號1)此時客戶端進(jìn)入FIN-WAIT-1(終止等待1)的狀態(tài)。TCP規(guī)定FIN報文段即使不攜帶數(shù)據(jù)也要消耗一個序號。服務(wù)端收到這個FIN他發(fā)回一個ACK(確認(rèn))確認(rèn)收到序號為收到序號1和SYN一樣一個FIN將占用一個序號。服務(wù)器收到連接釋放報文發(fā)出確認(rèn)報文ACK1acku1并且?guī)献约旱男蛄刑杝eqv此時服務(wù)端就進(jìn)入了CLOSE-WAIT關(guān)閉等待狀態(tài)。TCP服務(wù)器通知高層的應(yīng)用進(jìn)程客戶端向服務(wù)器的方向就釋放了這時候處于半關(guān)閉狀態(tài)即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了但是服務(wù)器若發(fā)送數(shù)據(jù)客戶端依然要接受。這個狀態(tài)還要持續(xù)一段時間也就是整個CLOSE-WAIT狀態(tài)持續(xù)的時間??蛻舳耸盏椒?wù)器的確認(rèn)請求后此時客戶端就進(jìn)入FIN-WAIT-2終止等待2狀態(tài)等待服務(wù)器發(fā)送連接釋放報文在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù)。服務(wù)端發(fā)送一個FIN(結(jié)束)到客戶端服務(wù)端關(guān)閉客戶端的連接。服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后就向客戶端發(fā)送連接釋放報文FIN1acku1由于在半關(guān)閉狀態(tài)服務(wù)器很可能又發(fā)送了一些數(shù)據(jù)假定此時的序列號為seqw此時服務(wù)器就進(jìn)入了LAST-ACK最后確認(rèn)狀態(tài)等待客戶端的確認(rèn)??蛻舳税l(fā)送ACK(確認(rèn))報文確認(rèn)并將確認(rèn)的序號1這樣關(guān)閉完成??蛻舳耸盏椒?wù)器的連接釋放報文后必須發(fā)出確認(rèn)ACK1ackw1而自己的序列號是sequ1此時客戶端就進(jìn)入了TIME-WAIT時間等待狀態(tài)。注意此時TCP連接還沒有釋放必須經(jīng)過2??MSL最長報文段壽命的時間后當(dāng)客戶端撤銷相應(yīng)的TCB后才進(jìn)入CLOSED狀態(tài)。服務(wù)器只要收到了客戶端發(fā)出的確認(rèn)立即進(jìn)入CLOSED狀態(tài)。同樣撤銷TCB后就結(jié)束了這次的TCP連接??梢钥吹椒?wù)器結(jié)束TCP連接的時間要比客戶端早一些。為什么是4次揮手呢為了確保數(shù)據(jù)能夠完成傳輸。關(guān)閉連接時當(dāng)收到對方的FIN報文通知時它僅僅表示對方?jīng)]有數(shù)據(jù)發(fā)送給你了但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了所以你可以未必會馬上會關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關(guān)閉連接了所以它這里的ACK報文和FIN報文多數(shù)情況下都是分開發(fā)送的??赡苡腥藭幸蓡杢cp我握手的時候為何ACK(確認(rèn))和SYN(建立連接)是一起發(fā)送。揮手的時候為什么是分開的時候發(fā)送呢.因為當(dāng)Server端收到Client端的SYN連接請求報文后可以直接發(fā)送SYNACK報文。其中ACK報文是用來應(yīng)答的SYN報文是用來同步的。但是關(guān)閉連接時當(dāng)Server端收到FIN報文時很可能并不會立即關(guān)閉 SOCKET所以只能先回復(fù)一個ACK報文告訴Client端“你發(fā)的FIN報文我收到了”。只有等到我Server端所有的報文都發(fā)送完了我才能發(fā)送FIN報文因此不能一起發(fā)送。故需要四步握手??蛻舳送蝗粧斓袅嗽趺崔k正常連接時客戶端突然掛掉了如果沒有措施處理這種情況那么就會出現(xiàn)客戶端和服務(wù)器端出現(xiàn)長時期的空閑。解決辦法是在服務(wù)器端設(shè)置?;钣嫊r器每當(dāng)服務(wù)器收到客戶端的消息就將計時器復(fù)位。超時時間通常設(shè)置為2小時。若服務(wù)器超過2小時沒收到客戶的信息他就發(fā)送探測報文段。若發(fā)送了10個探測報文段每一個相隔75秒還沒有響應(yīng)就認(rèn)為客戶端出了故障因而終止該連接。

相關(guān)新聞

第14章_HarmonyOs開發(fā)圖解 圖像

第14章_HarmonyOs開發(fā)圖解 圖像

第14章 HarmonyOs開發(fā)圖解 圖像HarmonyOS 學(xué)習(xí)系統(tǒng) | 階段三:高級深耕期學(xué)習(xí)目標(biāo)序號能力1掌握圖像解碼(ImageSource)與編碼(ImagePacker)的完整流程2能夠使用 PixelMap 進(jìn)行像素級操作3掌握圖像縮放、裁剪、EXIF 信息…

2026/7/28 19:18:31 閱讀更多
5分鐘掌握AI圖層分離神器:LayerDivider終極使用指南

5分鐘掌握AI圖層分離神器:LayerDivider終極使用指南

5分鐘掌握AI圖層分離神器:LayerDivider終極使用指南 【免費下載鏈接】layerdivider A tool to divide a single illustration into a layered structure. 項目地址: https://gitcode.com/gh_mirrors/la/layerdivider 你是否曾為手動分離復(fù)雜插畫圖層而煩惱&a…

2026/7/29 2:36:00 閱讀更多
規(guī)約管理化技術(shù)業(yè)務(wù)規(guī)則引擎實現(xiàn)

規(guī)約管理化技術(shù)業(yè)務(wù)規(guī)則引擎實現(xiàn)

規(guī)約管理化技術(shù)業(yè)務(wù)規(guī)則引擎實現(xiàn) 在當(dāng)今快速變化的商業(yè)環(huán)境中,企業(yè)需要高效、靈活地管理和執(zhí)行業(yè)務(wù)規(guī)則,以應(yīng)對復(fù)雜的業(yè)務(wù)需求。規(guī)約管理化技術(shù)業(yè)務(wù)規(guī)則引擎(Business Rules Engine, BRE)應(yīng)運而生,它通過將業(yè)務(wù)邏輯與…

2026/7/29 2:36:00 閱讀更多
面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

面試官大笑:“一個任務(wù)拆給 5 個 Subagent 并行跑,不比 1 個快 5 倍?“我搖頭:“快不了,還可能更慢“

前兩個月,我在重構(gòu) AlgoMooc 網(wǎng)站過程中,發(fā)現(xiàn)一個問題:在 Claude Code 里把一個任務(wù)拆給 5 個 Subagent 并行跑,結(jié)果可能比 1 個 agent 從頭干到尾還慢? 大多數(shù)人的第一反應(yīng)是反過來的:活是并行干的&#…

2026/7/29 0:15:24 閱讀更多
# 鴻蒙 HarmonyOS 應(yīng)用開發(fā)實戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號與動畫渲染精講

# 鴻蒙 HarmonyOS 應(yīng)用開發(fā)實戰(zhàn)(第25期)|骰子(Dice Roller)— Unicode 符號與動畫渲染精講

一、應(yīng)用概述 骰子(Dice Roller) 是一款經(jīng)典的休閑娛樂應(yīng)用,模擬了真實擲骰子的過程。應(yīng)用投擲兩個骰子(六面標(biāo)準(zhǔn)骰),使用 Unicode 骰面符號直觀展示每個骰子的點數(shù),并伴有快速滾動的動畫效果?!?/p>

2026/7/29 0:15:24 閱讀更多