Alamofire初探
Alamofire初探一. Alamofire概述二. URLSesstion基礎(chǔ)三、TCP的三次握手四、TCP數(shù)據(jù)的傳輸過(guò)程五、TCP的四次揮手一. Alamofire概述對(duì)于使用Objective-C的開(kāi)發(fā)者一定非常熟悉AFNetworking這個(gè)網(wǎng)絡(luò)框架。在蘋(píng)果推出的Swift之后AFNetworking的作者專門(mén)用Swift來(lái)編寫(xiě)一個(gè)類似AFNetworking的網(wǎng)絡(luò)框架稱為Alamofire。Alamofire地址因?yàn)锳lamofire是對(duì)蘋(píng)果URLSesstion的封裝,所以先來(lái)了解下URLSesstion的基礎(chǔ)二. URLSesstion基礎(chǔ)URLSession.shared.dataTask(with: url) { (data, response, error) in if error nil { print(請(qǐng)求成功\(String(describing: response)) ) } }.resume()此過(guò)程省略了一個(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ǔ)證書(shū)ephemeral:系統(tǒng)沒(méi)有任何持久性存儲(chǔ)所有內(nèi)容的生命周期與session相同當(dāng)session無(wú)效時(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í)符來(lái)進(jìn)行恢復(fù)。注意后臺(tái)session一定要在創(chuàng)建的時(shí)候賦予一個(gè)唯一的identifier,這樣在app下次運(yùn)行的時(shí)候能夠根據(jù)identifier來(lái)進(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) { // 下載完成 - 開(kāi)始沙盒遷移 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步開(kāi)啟后臺(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ù)下載回來(lái)) 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è)三次握手中的開(kāi)始表示客戶端想要和服務(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)志詢問(wèn)客戶端是否準(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)求沒(méi)有立即到達(dá)服務(wù)端而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)中滯留了直到某個(gè)時(shí)間才到達(dá)server本來(lái)這已經(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)建立起來(lái)了并一直等待客戶端發(fā)來(lái)的數(shù)據(jù)這樣server端很多資源都白白浪費(fèi)掉了采用三次握手就是為了防止這種情況的發(fā)生server會(huì)因?yàn)槭詹坏酱_認(rèn)的報(bào)文就知道客戶端并沒(méi)有建立連接這就是三次握手的作用。四、TCP數(shù)據(jù)的傳輸過(guò)程建立連接后兩臺(tái)主機(jī)就可以相互傳輸數(shù)據(jù)了。如下圖所示主機(jī)A初始seq為1200,滑動(dòng)窗體為100,向主機(jī)B傳遞數(shù)據(jù)的過(guò)程。假設(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傳來(lái)的ack(1301)后,開(kāi)始發(fā)送seq為1301,滑動(dòng)窗體為100的數(shù)據(jù)。…與三次握手協(xié)議相同最后加 1 是為了告訴對(duì)方要傳遞的 Seq 號(hào)。上面說(shuō)了主機(jī)B完全成功接收A發(fā)來(lái)的數(shù)據(jù)才是這樣的,如果存在丟包該如何下面分析傳輸過(guò)程中數(shù)據(jù)包丟失的情況如下圖所示上圖表示通過(guò) Seq 1301 數(shù)據(jù)包向主機(jī)B傳遞100字節(jié)的數(shù)據(jù)但中間發(fā)生了錯(cuò)誤主機(jī)B未收到。經(jīng)過(guò)一段時(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)沒(méi)有收到目標(biāo)機(jī)器傳回的 ACK 包那么定時(shí)器超時(shí)數(shù)據(jù)包會(huì)重傳。五、TCP的四次揮手TCP發(fā)送一個(gè)FIN(結(jié)束)用來(lái)關(guān)閉客戶端到服務(wù)端的連接客戶端進(jìn)程發(fā)出連接釋放報(bào)文并且停止發(fā)送數(shù)據(jù)。釋放數(shù)據(jù)報(bào)文首部FIN1,其序列號(hào)為sequ(等于前面已經(jīng)傳送過(guò)來(lái)的數(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)沒(méi)有數(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連接還沒(méi)有釋放必須經(jīng)過(guò)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ì)方來(lái)表示你同意現(xiàn)在可以關(guān)閉連接了所以它這里的ACK報(bào)文和FIN報(bào)文多數(shù)情況下都是分開(kāi)發(fā)送的??赡苡腥藭?huì)有疑問(wèn)tcp我握手的時(shí)候?yàn)楹蜛CK(確認(rèn))和SYN(建立連接)是一起發(fā)送。揮手的時(shí)候?yàn)槭裁词欠珠_(kāi)的時(shí)候發(fā)送呢.因?yàn)楫?dāng)Server端收到Client端的SYN連接請(qǐng)求報(bào)文后可以直接發(fā)送SYNACK報(bào)文。其中ACK報(bào)文是用來(lái)應(yīng)答的SYN報(bào)文是用來(lái)同步的。但是關(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í)客戶端突然掛掉了如果沒(méi)有措施處理這種情況那么就會(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ù)器超過(guò)2小時(shí)沒(méi)收到客戶的信息他就發(fā)送探測(cè)報(bào)文段。若發(fā)送了10個(gè)探測(cè)報(bào)文段每一個(gè)相隔75秒還沒(méi)有響應(yīng)就認(rèn)為客戶端出了故障因而終止該連接。

相關(guān)新聞

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

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

第14章 HarmonyOs開(kāi)發(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 閱讀更多
IP地址與子網(wǎng)掩碼計(jì)算:網(wǎng)絡(luò)排錯(cuò)與規(guī)劃的必備基本功

IP地址與子網(wǎng)掩碼計(jì)算:網(wǎng)絡(luò)排錯(cuò)與規(guī)劃的必備基本功

1. 從一次真實(shí)的網(wǎng)絡(luò)故障說(shuō)起:為什么IP計(jì)算是基本功那天下午,整個(gè)辦公室的網(wǎng)絡(luò)突然變得奇慢無(wú)比,部分同事甚至完全無(wú)法訪問(wèn)內(nèi)部的文件服務(wù)器。作為團(tuán)隊(duì)里對(duì)網(wǎng)絡(luò)稍有了解的人,我被叫去幫忙。初步排查,路由器和交換機(jī)指示…

2026/7/29 4:56:04 閱讀更多
AI監(jiān)控濫用已致37起跨國(guó)訴訟:企業(yè)級(jí)倫理審查清單(含實(shí)時(shí)行為分析、情感識(shí)別、員工監(jiān)工三大禁區(qū))

AI監(jiān)控濫用已致37起跨國(guó)訴訟:企業(yè)級(jí)倫理審查清單(含實(shí)時(shí)行為分析、情感識(shí)別、員工監(jiān)工三大禁區(qū))

更多請(qǐng)點(diǎn)擊: https://kaifayun.com 第一章:AI監(jiān)控濫用已致37起跨國(guó)訴訟:企業(yè)級(jí)倫理審查清單(含實(shí)時(shí)行為分析、情感識(shí)別、員工監(jiān)工三大禁區(qū)) 全球范圍內(nèi),AI驅(qū)動(dòng)的職場(chǎng)監(jiān)控系統(tǒng)正引發(fā)前所未有的法律與倫理危…

2026/7/29 4:56:04 閱讀更多
Verilog計(jì)數(shù)器設(shè)計(jì)全解析:從基礎(chǔ)原理到高級(jí)應(yīng)用與避坑指南

Verilog計(jì)數(shù)器設(shè)計(jì)全解析:從基礎(chǔ)原理到高級(jí)應(yīng)用與避坑指南

1. 從“數(shù)數(shù)”到“時(shí)序控制”:計(jì)數(shù)器的核心價(jià)值在數(shù)字電路和FPGA/ASIC設(shè)計(jì)的世界里,計(jì)數(shù)器(Counter)可能是你接觸到的第一個(gè),也是貫穿整個(gè)職業(yè)生涯最基礎(chǔ)、最核心的時(shí)序邏輯電路。它遠(yuǎn)不止是“數(shù)數(shù)”那么簡(jiǎn)單。當(dāng)你需要…

2026/7/29 4:56:04 閱讀更多
CentOS 7 C語(yǔ)言開(kāi)發(fā)環(huán)境搭建:從yum軟件包組到Hello World實(shí)戰(zhàn)

CentOS 7 C語(yǔ)言開(kāi)發(fā)環(huán)境搭建:從yum軟件包組到Hello World實(shí)戰(zhàn)

1. 項(xiàng)目概述:在CentOS 7上構(gòu)建C語(yǔ)言開(kāi)發(fā)環(huán)境很多剛接觸Linux系統(tǒng)編程的朋友,尤其是從Windows環(huán)境轉(zhuǎn)過(guò)來(lái)的,第一個(gè)攔路虎往往不是語(yǔ)法本身,而是“環(huán)境怎么搭”。在Windows下,你可能下載一個(gè)Visual Studio,安…

2026/7/29 4:56:04 閱讀更多
步進(jìn)電機(jī)驅(qū)動(dòng)器核心參數(shù)解析與實(shí)戰(zhàn)選型指南

步進(jìn)電機(jī)驅(qū)動(dòng)器核心參數(shù)解析與實(shí)戰(zhàn)選型指南

1. 項(xiàng)目概述:從“會(huì)轉(zhuǎn)”到“轉(zhuǎn)得好”的必經(jīng)之路提起步進(jìn)電機(jī),很多搞過(guò)單片機(jī)、玩過(guò)3D打印機(jī)或者DIY過(guò)一些小裝置的朋友肯定不陌生。它最大的特點(diǎn)就是“聽(tīng)話”——給一個(gè)脈沖,它就轉(zhuǎn)一個(gè)固定的角度,開(kāi)環(huán)控制,結(jié)構(gòu)簡(jiǎn)單&a…

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

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

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

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

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

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

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