Alamofire初探
Alamofire初探一. Alamofire概述二. URLSesstion基礎(chǔ)三、TCP的三次握手四、TCP數(shù)據(jù)的傳輸過程五、TCP的四次揮手一. Alamofire概述對(duì)于使用Objective-C的開發(fā)者一定非常熟悉AFNetworking這個(gè)網(wǎng)絡(luò)框架。在蘋果推出的Swift之后AFNetworking的作者專門用Swift來編寫一個(gè)類似AFNetworking的網(wǎng)絡(luò)框架稱為Alamofire。Alamofire地址因?yàn)锳lamofire是對(duì)蘋果URLSesstion的封裝,所以先來了解下URLSesstion的基礎(chǔ)二. URLSesstion基礎(chǔ)URLSession.shared.dataTask(with: url) { (data, response, error) in if error nil { print(請(qǐng)求成功\(String(describing: response)) ) } }.resume()此過程省略了一個(gè)重要的東西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)會(huì)創(chuàng)建一個(gè)持久化的緩存并在用戶的鑰匙串中存儲(chǔ)證書ephemeral:系統(tǒng)沒有任何持久性存儲(chǔ)所有內(nèi)容的生命周期與session相同當(dāng)session無效時(shí)所有內(nèi)容自動(dòng)釋放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)建一個(gè)可以在后臺(tái)甚至app已經(jīng)關(guān)閉的時(shí)候仍然在傳輸數(shù)據(jù)的會(huì)話。background模式可以在程序掛起退出崩潰的情況下運(yùn)行task.也可以利用標(biāo)識(shí)符來進(jìn)行恢復(fù)。注意后臺(tái)session一定要在創(chuàng)建的時(shí)候賦予一個(gè)唯一的identifier,這樣在app下次運(yùn)行的時(shí)候能夠根據(jù)identifier來進(jìn)行相關(guān)的區(qū)分如果用戶關(guān)閉了app,ios系統(tǒng)會(huì)關(guān)閉所有的background Session.而且被用戶強(qiáng)制關(guān)閉了以后iOS系統(tǒng)不回主動(dòng)喚醒a(bǔ)pp,只有用戶下次啟動(dòng)了app,數(shù)據(jù)傳輸才會(huì)繼續(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 //拷貝到用戶目錄文件名以時(shí)間戳命名 let documnets NSHomeDirectory() /Documents/ self.lgCurrentDataTurnString() .mp4 print(移動(dòng)地址:\(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á)到后臺(tái)下載還需要設(shè)置下面2步開啟后臺(tái)下載權(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.)用于保存后臺(tái)下載的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)及時(shí)更新屏幕func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { print(后臺(tái)任務(wù)下載回來) DispatchQueue.main.async { guard let appDelegate UIApplication.shared.delegate as? AppDelegate, let backgroundHandle appDelegate.backgroundSessionCompletionHandler else { return } backgroundHandle() } }三、TCP的三次握手http請(qǐng)求是基于tcp連接的tcp有6種表示位SYN(synchronous建立聯(lián)機(jī))ACK(acknowledgement確認(rèn))PSH(push傳送)FIN(finish結(jié)束)RST(reset重置)URG(urgent緊急)sequence number(順序號(hào)碼)acknowledge number(確認(rèn)號(hào)碼)客戶端向服務(wù)器發(fā)出連接請(qǐng)求報(bào)文這時(shí)報(bào)文首部中的同部位SYN1,同時(shí)隨機(jī)生成初始序列號(hào)seqx,此時(shí)TCP客戶端進(jìn)程進(jìn)入了SYN-SENT(同步已發(fā)送狀態(tài))狀態(tài)。TCP規(guī)定SYN報(bào)文段(SYN1的報(bào)文段)不能攜帶數(shù)據(jù)但需要消耗掉一個(gè)序號(hào)。這個(gè)三次握手中的開始表示客戶端想要和服務(wù)端建立連接。TCP服務(wù)器收到請(qǐng)求報(bào)文后如果同意連接則發(fā)出確認(rèn)報(bào)文確認(rèn)報(bào)文中應(yīng)該ACK1,SYN1,確認(rèn)號(hào)是ackx1,同時(shí)也要自己隨機(jī)初始化一個(gè)序列號(hào)seqy,此時(shí)TCP服務(wù)器進(jìn)程進(jìn)入了SYN-RCVD(同步收到)狀態(tài)這個(gè)報(bào)文也不能攜帶數(shù)據(jù)但是同樣要消耗一個(gè)序號(hào)。這個(gè)報(bào)文帶有SYN(建立連接)和ACK(確認(rèn))標(biāo)志詢問客戶端是否準(zhǔn)備好。TCP客戶進(jìn)程收到確認(rèn)后還要向服務(wù)器給出確認(rèn)。確認(rèn)報(bào)文的ACK1,acky1,此時(shí)TCP連接建立客戶端進(jìn)入ESTABLISHED(已建立連接)狀態(tài)TCP規(guī)定ACK報(bào)文段可以攜帶數(shù)據(jù)但是如果不攜帶數(shù)據(jù)則不消耗序號(hào)這里客戶端表示我已經(jīng)準(zhǔn)備好。為什么要三次握手呢舉例已失效的連接請(qǐng)求報(bào)文段客戶端發(fā)送了第一個(gè)連接的請(qǐng)求報(bào)文但由于網(wǎng)絡(luò)不好這個(gè)請(qǐng)求沒有立即到達(dá)服務(wù)端而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中滯留了直到某個(gè)時(shí)間才到達(dá)server本來這已經(jīng)是一個(gè)失效的報(bào)文但是server端收到這個(gè)請(qǐng)求報(bào)文后還是會(huì)像客戶端發(fā)送確認(rèn)的報(bào)文,表示同意連接。假如不采用三次握手那么server發(fā)出確認(rèn)后新的建立就連接了但其實(shí)這個(gè)請(qǐng)求是失效的請(qǐng)求客戶端是不會(huì)理睬server端的確認(rèn)信息的也不會(huì)像服務(wù)端發(fā)送確認(rèn)的請(qǐng)求,但是server認(rèn)為新的連接已經(jīng)建立起來了并一直等待客戶端發(fā)來的數(shù)據(jù)這樣server端很多資源都白白浪費(fèi)掉了采用三次握手就是為了防止這種情況的發(fā)生server會(huì)因?yàn)槭詹坏酱_認(rèn)的報(bào)文就知道客戶端并沒有建立連接這就是三次握手的作用。四、TCP數(shù)據(jù)的傳輸過程建立連接后兩臺(tái)主機(jī)就可以相互傳輸數(shù)據(jù)了。如下圖所示主機(jī)A初始seq為1200,滑動(dòng)窗體為100,向主機(jī)B傳遞數(shù)據(jù)的過程。假設(shè)主機(jī)B在完全成功接收數(shù)據(jù)的基礎(chǔ)上,那么主機(jī)B為了確認(rèn)這一點(diǎn)向主機(jī)A發(fā)送 ACK 包并將 Ack 號(hào)設(shè)置為 1301。因此按如下的公式確認(rèn) Ack 號(hào)Ack號(hào) Seq號(hào) 傳遞的字節(jié)數(shù) 1 這是在完全接受成功的情況下主機(jī)A獲得B傳來的ack(1301)后,開始發(fā)送seq為1301,滑動(dòng)窗體為100的數(shù)據(jù)?!c三次握手協(xié)議相同最后加 1 是為了告訴對(duì)方要傳遞的 Seq 號(hào)。上面說了主機(jī)B完全成功接收A發(fā)來的數(shù)據(jù)才是這樣的,如果存在丟包該如何下面分析傳輸過程中數(shù)據(jù)包丟失的情況如下圖所示上圖表示通過 Seq 1301 數(shù)據(jù)包向主機(jī)B傳遞100字節(jié)的數(shù)據(jù)但中間發(fā)生了錯(cuò)誤主機(jī)B未收到。經(jīng)過一段時(shí)間后主機(jī)A仍未收到對(duì)于 Seq 1301 的ACK確認(rèn)因此嘗試重傳數(shù)據(jù)。為了完成數(shù)據(jù)包的重傳TCP套接字每次發(fā)送數(shù)據(jù)包時(shí)都會(huì)啟動(dòng)定時(shí)器如果在一定時(shí)間內(nèi)沒有收到目標(biāo)機(jī)器傳回的 ACK 包那么定時(shí)器超時(shí)數(shù)據(jù)包會(huì)重傳。五、TCP的四次揮手TCP發(fā)送一個(gè)FIN(結(jié)束)用來關(guān)閉客戶端到服務(wù)端的連接客戶端進(jìn)程發(fā)出連接釋放報(bào)文并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報(bào)文首部FIN1,其序列號(hào)為sequ(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)1)此時(shí)客戶端進(jìn)入FIN-WAIT-1(終止等待1)的狀態(tài)。TCP規(guī)定FIN報(bào)文段即使不攜帶數(shù)據(jù)也要消耗一個(gè)序號(hào)。服務(wù)端收到這個(gè)FIN他發(fā)回一個(gè)ACK(確認(rèn))確認(rèn)收到序號(hào)為收到序號(hào)1和SYN一樣一個(gè)FIN將占用一個(gè)序號(hào)。服務(wù)器收到連接釋放報(bào)文發(fā)出確認(rèn)報(bào)文ACK1acku1并且?guī)献约旱男蛄刑?hào)seqv此時(shí)服務(wù)端就進(jìn)入了CLOSE-WAIT關(guān)閉等待狀態(tài)。TCP服務(wù)器通知高層的應(yīng)用進(jìn)程客戶端向服務(wù)器的方向就釋放了這時(shí)候處于半關(guān)閉狀態(tài)即客戶端已經(jīng)沒有數(shù)據(jù)要發(fā)送了但是服務(wù)器若發(fā)送數(shù)據(jù)客戶端依然要接受。這個(gè)狀態(tài)還要持續(xù)一段時(shí)間也就是整個(gè)CLOSE-WAIT狀態(tài)持續(xù)的時(shí)間??蛻舳耸盏椒?wù)器的確認(rèn)請(qǐng)求后此時(shí)客戶端就進(jìn)入FIN-WAIT-2終止等待2狀態(tài)等待服務(wù)器發(fā)送連接釋放報(bào)文在這之前還需要接受服務(wù)器發(fā)送的最后的數(shù)據(jù)。服務(wù)端發(fā)送一個(gè)FIN(結(jié)束)到客戶端服務(wù)端關(guān)閉客戶端的連接。服務(wù)器將最后的數(shù)據(jù)發(fā)送完畢后就向客戶端發(fā)送連接釋放報(bào)文FIN1acku1由于在半關(guān)閉狀態(tài)服務(wù)器很可能又發(fā)送了一些數(shù)據(jù)假定此時(shí)的序列號(hào)為seqw此時(shí)服務(wù)器就進(jìn)入了LAST-ACK最后確認(rèn)狀態(tài)等待客戶端的確認(rèn)??蛻舳税l(fā)送ACK(確認(rèn))報(bào)文確認(rèn)并將確認(rèn)的序號(hào)1這樣關(guān)閉完成??蛻舳耸盏椒?wù)器的連接釋放報(bào)文后必須發(fā)出確認(rèn)ACK1ackw1而自己的序列號(hào)是sequ1此時(shí)客戶端就進(jìn)入了TIME-WAIT時(shí)間等待狀態(tài)。注意此時(shí)TCP連接還沒有釋放必須經(jīng)過2??MSL最長(zhǎng)報(bào)文段壽命的時(shí)間后當(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連接的時(shí)間要比客戶端早一些。為什么是4次揮手呢為了確保數(shù)據(jù)能夠完成傳輸。關(guān)閉連接時(shí)當(dāng)收到對(duì)方的FIN報(bào)文通知時(shí)它僅僅表示對(duì)方?jīng)]有數(shù)據(jù)發(fā)送給你了但未必你所有的數(shù)據(jù)都全部發(fā)送給對(duì)方了所以你可以未必會(huì)馬上會(huì)關(guān)閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對(duì)方之后再發(fā)送FIN報(bào)文給對(duì)方來表示你同意現(xiàn)在可以關(guān)閉連接了所以它這里的ACK報(bào)文和FIN報(bào)文多數(shù)情況下都是分開發(fā)送的。可能有人會(huì)有疑問tcp我握手的時(shí)候?yàn)楹蜛CK(確認(rèn))和SYN(建立連接)是一起發(fā)送。揮手的時(shí)候?yàn)槭裁词欠珠_的時(shí)候發(fā)送呢.因?yàn)楫?dāng)Server端收到Client端的SYN連接請(qǐng)求報(bào)文后可以直接發(fā)送SYNACK報(bào)文。其中ACK報(bào)文是用來應(yīng)答的SYN報(bào)文是用來同步的。但是關(guān)閉連接時(shí)當(dāng)Server端收到FIN報(bào)文時(shí)很可能并不會(huì)立即關(guān)閉 SOCKET所以只能先回復(fù)一個(gè)ACK報(bào)文告訴Client端“你發(fā)的FIN報(bào)文我收到了”。只有等到我Server端所有的報(bào)文都發(fā)送完了我才能發(fā)送FIN報(bào)文因此不能一起發(fā)送。故需要四步握手。客戶端突然掛掉了怎么辦正常連接時(shí)客戶端突然掛掉了如果沒有措施處理這種情況那么就會(huì)出現(xiàn)客戶端和服務(wù)器端出現(xiàn)長(zhǎng)時(shí)期的空閑。解決辦法是在服務(wù)器端設(shè)置保活計(jì)時(shí)器每當(dāng)服務(wù)器收到客戶端的消息就將計(jì)時(shí)器復(fù)位。超時(shí)時(shí)間通常設(shè)置為2小時(shí)。若服務(wù)器超過2小時(shí)沒收到客戶的信息他就發(fā)送探測(cè)報(bào)文段。若發(fā)送了10個(gè)探測(cè)報(bào)文段每一個(gè)相隔75秒還沒有響應(yīng)就認(rèn)為客戶端出了故障因而終止該連接。

相關(guān)新聞

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

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

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

2026/7/28 19:18:31 閱讀更多
python爬取貝殼中二手房的數(shù)據(jù)

python爬取貝殼中二手房的數(shù)據(jù)

前言:通過代碼爬取貝殼中二手房的數(shù)據(jù),以此給更多需要了解爬蟲或者二手房信息的人提供便利。 第一部分:爬取地址 1.1貝殼首頁地址 jiujiang.ke.com 第二部分:爬取數(shù)據(jù) 2.1輸入要爬多少頁 int(input(輸入一共要多少頁&#xf…

2026/7/29 4:26:03 閱讀更多
從零吃透C語言數(shù)組基礎(chǔ)!告別新手報(bào)錯(cuò),小白看完直接上手

從零吃透C語言數(shù)組基礎(chǔ)!告別新手報(bào)錯(cuò),小白看完直接上手

從零吃透C語言數(shù)組基礎(chǔ)!告別新手報(bào)錯(cuò),小白看完直接上手 ** 學(xué)完C語言函數(shù)之后,我本以為自己已經(jīng)入門了,寫個(gè)簡(jiǎn)單計(jì)算、循環(huán)代碼都不在話下。結(jié)果沒過兩天就遇到了新難題:需要一次性存儲(chǔ)幾十個(gè)學(xué)生的成績(jī),挨…

2026/7/29 4:26:03 閱讀更多
學(xué)習(xí)日記 7.28

學(xué)習(xí)日記 7.28

在機(jī)器學(xué)習(xí)的學(xué)習(xí)之路上,線性回歸和邏輯回歸是兩塊重要的基石。今天我們將通過兩個(gè)實(shí)戰(zhàn)案例,從理論到代碼,全面掌握這兩種算法的應(yīng)用:案例一:多元線性回歸 —— 根據(jù)體重和年齡預(yù)測(cè)血壓收縮壓;案例二&#…

2026/7/29 4:26:03 閱讀更多
AI數(shù)字人口播訓(xùn)練全周期,從唇形同步誤差<0.3幀到通過抖音AIGC白名單認(rèn)證

AI數(shù)字人口播訓(xùn)練全周期,從唇形同步誤差<0.3幀到通過抖音AIGC白名單認(rèn)證

更多請(qǐng)點(diǎn)擊: https://intelliparadigm.com 第一章:AI數(shù)字人口播訓(xùn)練全周期概覽 AI數(shù)字人口播訓(xùn)練是一項(xiàng)融合語音合成、表情驅(qū)動(dòng)、語義理解與多模態(tài)對(duì)齊的系統(tǒng)性工程,其全周期涵蓋數(shù)據(jù)準(zhǔn)備、模型微調(diào)、驅(qū)動(dòng)策略設(shè)計(jì)、實(shí)時(shí)渲染優(yōu)化及效果評(píng)估五…

2026/7/29 4:26:03 閱讀更多
極驗(yàn)3代點(diǎn)選驗(yàn)證碼逆向:從抓包到生成加密w參數(shù)的完整實(shí)戰(zhàn)

極驗(yàn)3代點(diǎn)選驗(yàn)證碼逆向:從抓包到生成加密w參數(shù)的完整實(shí)戰(zhàn)

1. 項(xiàng)目概述:為什么我們要啃下極驗(yàn)3代點(diǎn)選這塊硬骨頭?如果你做過爬蟲,尤其是需要處理登錄、注冊(cè)或者高頻數(shù)據(jù)抓取,那你一定對(duì)“極驗(yàn)”這個(gè)名字不陌生。它就像一道橫在數(shù)據(jù)洪流前的智能閘門,而其中的點(diǎn)選驗(yàn)證碼&#xf…

2026/7/29 4:26:03 閱讀更多
嵌入式設(shè)備與云端安全連接方案及優(yōu)化技巧

嵌入式設(shè)備與云端安全連接方案及優(yōu)化技巧

1. 項(xiàng)目背景與硬件選型解析當(dāng)我們需要在嵌入式設(shè)備與云端建立安全連接時(shí),硬件平臺(tái)的選擇直接影響著整個(gè)系統(tǒng)的性能和可靠性。這個(gè)項(xiàng)目中選用的A5000顯卡和TM4C123GH6PZ微控制器組合,恰好覆蓋了從邊緣計(jì)算到云端協(xié)同的全鏈路需求。NVIDIA RTX A5000作為?!?/p>

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

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

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

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

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

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

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