NSURLSessionTask
是對網絡會話的管理者 NSURLSession
創(chuàng)建任務的封裝,它僅僅是個抽象的基類,實際使用中可以劃分為不同的任務:
-
NSURLSessionDataTask
:數據任務杉女,使用NSData
對象發(fā)送和接收數據;數據任務旨在向服務器發(fā)出簡短的阿逃,經常是交互式的請求逸绎;支持默認會話骡男、臨時會話淆游,但不支持后臺會話;
通過對代理方法-URLSession:dataTask:didReceiveData:
的一系列調用來接收資源隔盛;該任務供使用者立即解析犹菱。 -
NSURLSessionUploadTask
:上傳任務,與數據任務相似骚亿,但是它們還發(fā)送數據(通常以文件形式)已亥,并在應用程序不運行時支持后臺上傳;
通過引用要上傳的文件或數據對象来屠,或利用-URLSession:task:needNewBodyStream:
來提供上傳主體顯式創(chuàng)建的虑椎;與數據任務的區(qū)別在于實例構造方式不同震鹉! -
NSURLSessionDownloadTask
:下載任務,直接將響應數據寫入臨時文件捆姜,任何類型的會話都支持下載和上傳任務传趾。
任務完成后,delegate
調用-URLSession:downloadTask:didFinishDownloadingToURL:
在適當時機將該文件移動到沙盒的永久位置泥技、或者讀取該文件浆兰;
如果取消任務,NSURLSessionDownloadTask
可以生成一個data blob
珊豹,用于稍后恢復下載簸呈。 -
NSURLSessionWebSocketTask
:WebSocket
任務,使用RFC 6455
中定義的WebSocket
協議通過TCP和TLS交換消息店茶。 -
NSURLSessionStreamTask
:從 iOS9 開始支持該任務蜕便,這允許TCP/IP連接到指定的主機和可選的安全握手和代理導航的端口;
通過NSURLSession
創(chuàng)建任務贩幻,有兩種響應方式:
- 設置
delegate
:響應報文被NSURLSessionDelegate
的代理方法處理轿腺; - 使用
completionHandler
創(chuàng)建任務,那么在completionHandler
中處理響應數據(即使設置了delegate
)丛楚;
如果設置了delegate
族壳,根據不通的任務,由不同的 NSURLSessionDelegate
方法來處理:
-
NSURLSessionDelegate
: 是 session 級別的協議趣些,主要管理 session 的生命周期仿荆、處理證書認證等 -
NSURLSessionTaskDelegate
: 是 task 級別的協議,面向所有的委托方法 -
NSURLSessionDataDelegate
: 是 task 級別的協議坏平,主要用來處理 data 和 upload赖歌,如接收到響應,接收到數據功茴,是否緩存數據 -
NSURLSession?Download?Delegate
: 是 task 級別的協議,用來處理下載任務 -
NSURLSessionStreamDelegate
: 是 task 級別的協議孽亲,用來處理 streamTask -
NSURLSessionWebSocketDelegate
: 是 task 級別的委托坎穿,處理特定于 WebSocketTask 的事件
可以重復使用一個NSURLSession
來創(chuàng)建多個任務,創(chuàng)建的 NSURLSessionTask
對象總是處于掛起狀態(tài)返劲,在它們執(zhí)行之前必須調用 -resume
方法玲昧。啟動任務之后NSURLSession
對該任務持有強引用,直到任務完成或者失斃郝獭孵延!
1、NSURLSessionTask
API
NSURLSessionTask
只能通過 NSURLSession
的實例方法獲取亲配,不能使用-init
尘应、+new
創(chuàng)建惶凝!
所有任務屬性都支持鍵值觀察!
1.1犬钢、獲取任務信息
/** 當前任務的請求對象
* @note 通常與 originalRequest 相同苍鲜,除非服務器以重定向到不同URL的方式響應初始請求
*/
@property (nullable, readonly, copy) NSURLRequest *currentRequest;
/** 創(chuàng)建任務時傳遞的原始請求對象;
* 如果是一個streamTask玷犹,則可能為 nil
* @note 通常與 currentRequest 相同混滔,除非服務器以重定向到不同URL的方式響應初始請求
*/
@property (nullable, readonly, copy) NSURLRequest *originalRequest;
/** 服務器對 currentRequest 的響應信息
* 包含關于服務器提供的請求信息,此信息始終包含originalRequest歹颓;它還可能包含預期的數據長度坯屿、MIME類型信息、編碼信息巍扛、建議的文件名等领跛;
* @note 如果沒有收到服務器的回應,可能為 nil
*/
@property (nullable, readonly, copy) NSURLResponse *response;
/** 該任務的標識符电湘,由所屬的 NSURLSession 實例分配隔节,且具有唯一性
* @note 在不同 NSURLSession 中的任務,可能具有相同的 taskIdentifier 寂呛;
*/
@property (readonly) NSUInteger taskIdentifier;
/** 開發(fā)人員為任務提供的描述怎诫,可用于調試程序、追蹤任務贷痪、或直接顯示給用戶幻妓!
* @note 系統(tǒng)不會設置該值,可能是 nil劫拢;
*/
@property (nullable, copy) NSString *taskDescription;
/** 任務失敗的錯誤信息
* 如果有錯誤肉津,由代理方法 -URLSession:task:didCompleteWithError 返回
* 如果沒有錯誤,該值為 nil
*/
@property (nullable, readonly, copy) NSError *error;
1.2舱沧、任務進展
/** 任務進度 */
@property (readonly, strong) NSProgress *progress API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/** 響應數據的預期長度妹沙,通常在 HTTP 響應頭的 Content-Length 字段;
* 如果響應頭沒有該字段熟吏,則此值為 NSURLSessionTransferSizeUnknown
*/
@property (readonly) int64_t countOfBytesExpectedToReceive;
/** 從服務器已接收到的body字節(jié)數
* 沒有body預期距糖,字節(jié)數可能是零;
* 如果不知道字節(jié)數牵寺,值為 NSURLSessionTransferSizeUnknown悍引;
* @note 如果需要監(jiān)測該值的變化,需要實現某個代理方法:
* <li> 用于上傳任務帽氓,實現 -URLSession:dataTask:didReceiveData: 方法
* <li> 用于下載任務趣斤,實現 -URLSession:downloadTask:didWriteData:totalBytesWritten:totalbytestowrite: 方法
*/
@property (readonly) int64_t countOfBytesReceived;
/** 請求體 requestBody 的預計長度,在 HTTP 請求頭的 Content-Length 字段設置
* 可以通過三種方式預估請求體的長度:
* <1>數據對象 upload body 的長度
* <2>上傳任務(而不是下載任務) :從磁盤上獲取上傳文件主體的長度
* <3>從 NSURLRequest 對象中獲取 Content-Length
*
* @note 如果提供 stream 或 body data黎休,則值為NSURLSessionTransferSizeUnknown;
* 如果不提供 stream 或 body data浓领,則值為0
*/
@property (readonly) int64_t countOfBytesExpectedToSend;
/** 已發(fā)送到服務器的 body 的字節(jié)數
* 監(jiān)聽該值的改變玉凯,需要實現代理方法:
* -URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
* @note 只統(tǒng)計請求體的字節(jié)數,不包括請求頭
*/
@property (readonly) int64_t countOfBytesSent;
1.3镊逝、調度任務
/** 客戶端通過該任務預計將發(fā)送或者接收的最大字節(jié)數
* 設置該值應考慮 HTTP headers 和body 或者 body stream 的大凶嘲 ;
* 如果未設定該值撑蒜,系統(tǒng)使用默認值 NSURLSessionTransferSizeUnknown歹啼;
* 系統(tǒng)使用該值來優(yōu)化 UNSURLSessionTask 的調度,因此建議提供一個近似值座菠,而不是接受默認值狸眼。
*/
@property int64_t countOfBytesClientExpectsToSend API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property int64_t countOfBytesClientExpectsToReceive API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/** 設置網絡加載開始的最早時間
* 該值并不能保證網絡加載將在指定時間開始,僅保證加載不會提前開始浴滴;如果未設置拓萌,則不使用啟動延遲。
* 該值僅適用于從后臺NSURLSession創(chuàng)建的任務升略;其它類型會話創(chuàng)建的任務無效微王;
*/
@property (nullable, copy) NSDate *earliestBeginDate API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
1.4、控制任務狀態(tài)
/** 取消任務:正在執(zhí)行的任務品嚣、已經掛起的任務炕倘;
* 該方法立即返回,將任務標記為被取消翰撑。
* 當任務被標記為被取消時罩旋,代理方法 -URLSession:task:didCompleteWithError: 收到一個 NSURLErrorCancelled 的錯誤
*/
- (void)cancel;
/** 臨時掛起任務:會阻止 NSURLSession 繼續(xù)加載數據
* 任務在被掛起時不會產生網絡流量,與任務關聯的超時計時器將被禁用 -> 不受超時限制眶诈;
* 下載任務可以在稍后繼續(xù)傳輸數據涨醋,但其它任務必須重新開始 -resume ;
* 可能仍有此任務的代理方法被調用逝撬,例如在掛起時收到的數據浴骂,但在 -resume 發(fā)送之前,不會再使用代理方法進行數據傳輸宪潮;
*/
- (void)suspend;
/** 恢復被掛起的任務
* 剛初始化的任務處于掛起狀態(tài)靠闭,需要調用此方法來啟動任務
*/
- (void)resume;
/** 任務的當前狀態(tài)(活動的、掛起的坎炼、正在取消、完成)
* <ul> NSURLSessionTaskState 的枚舉值
* <li> NSURLSessionTaskStateRunning 任務正在進行拦键,此時任務受限于 Configuration 中指定的請求和資源超時時間
* <li> NSURLSessionTaskStateSuspended 任務暫停谣光,在任務恢復之前,不會進行進一步的處理芬为;此時任務不受超時限制萄金;
* <li> NSURLSessionTaskStateCanceling 任務取消蟀悦;會話將收到代理方法 -URLSession:task:didCompleteWithError:
* <li> NSURLSessionTaskStateCompleted 任務已經完成(沒有被取消),會話將不再收到代理方法氧敢;
* 如果成功完成日戈,則屬性error為nil;否則提供錯誤信息孙乖。
* </ul>
*/
@property (readonly) NSURLSessionTaskState state;
/** 主機處理該任務的相對優(yōu)先級浙炼,指定為0.0(最低優(yōu)先級)和1.0(最高優(yōu)先級)之間的浮點值
* @discussion 優(yōu)先級只提供一個提示,而不是任務執(zhí)行的硬性要求唯袄,并不保證性能弯屈;
* 任務的優(yōu)先級可以在任何時候改變,但不是所有的網絡協議都支持這個;在這些情況下恋拷,將使用最后一個生效的優(yōu)先級资厉。
* <ul> 系統(tǒng)提供的優(yōu)先級
* <li> NSURLSessionTaskPriorityDefault 默認優(yōu)先級,值為0.5蔬顾,用于任何未指定優(yōu)先級的任務宴偿;
* <li> NSURLSessionTaskPriorityLow 低優(yōu)先級,值高于最小值0诀豁,低于默認值
* <li> NSURLSessionTaskPriorityHigh 高優(yōu)先級窄刘,其值高于默認值,低于最大值 1.0
* </ul>
* 除了系統(tǒng)提供的這個三優(yōu)先級且叁,還可以使用 0 ~ 1.0 之間的任何浮點值
*/
@property float priority API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
2都哭、數據任務NSURLSessionDataTask
NSURLSessionDataTask
數據任務:直接將下載的數據作為一個或多個NSData
返回到應用程序的內存中;是NSURLSessionTask
的一個子類逞带,在 NSURLSessionTask
基礎上不提供任何額外的功能欺矫,僅僅是詞義的區(qū)別。當使用數據任務:
- 在
body data
上傳期間展氓,NSURLSession
定期調用代理方法-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
獲取狀態(tài)信息穆趴; - 在接收到初始響應后,
NSURLSession
調用代理方法-URLSession:dataTask:didReceiveResponse:completionHandler:
檢查狀態(tài)代碼和響應頭遇汞,并可選地將數據任務轉換為下載任務未妹; - 在數據傳輸過程中,
NSURLSession
調用代理方法-URLSession:dataTask:didReceiveData:
接收數據空入; - 完成后络它,
NSURLSession
調用代理方法-URLSession:dataTask:willCacheResponse:completionHandler:
確定是否應該緩存響應
3、上傳任務NSURLSessionUploadTask
NSURLSessionUploadTask
上傳任務:用于需要 request body
的 HTTP 請求歪赢,如 POST 或 PUT 化戳;它是數據任務 NSURLSessionDataTask
的一個子類,在 NSURLSessionDataTask
基礎上不提供任何額外的功能埋凯,與數據任務對比:
- <li> 需要調用
NSURLSession
上的不同方法來創(chuàng)建上傳任務 - <li> 如果服務器提供一個響應点楼,上傳任務將該響應作為一個或多個
NSData
對象返回到內存中扫尖。 - <li> 與數據任務不同,支持在后臺上傳內容掠廓;
- <li>
NSURLSessionDataTask
的所有代理方法同樣適用于NSURLSessionUploadTasks
换怖;
創(chuàng)建上傳任務時,需要提供一個URLRequest
實例蟀瞧,該實例包含請求頭的某些字段沉颂,如 content-Type
、content-Disposition
等黄橘。
- 在iOS中兆览,當在后臺會話創(chuàng)建上傳任務時,系統(tǒng)會將該待上傳文件復制到一個臨時位置塞关;
- 在上傳過程中
NSURLSession
定期調用代理方法-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
獲取狀態(tài)信息抬探; - 當請求的上傳階段結束時,該任務的行為類似于數據任務帆赢,調用代理方法來提供服務器的響應頭小压、狀態(tài)代碼、內容數據等椰于。
4怠益、下載任務NSURLSessionDownloadTask
NSURLSessionDownloadTask
下載任務:將遠程文件下載到本地;是NSURLSessionTask
的一個子類瘾婿,在 NSURLSessionTask
基礎上提供新的功能蜻牢;
- 下載任務直接將服務器的響應數據寫入臨時文件,當數據從服務器到達時偏陪,為用應程序提供進度更新抢呆;
- 在后臺會話中使用下載任務時,即使應用程序處于掛起狀態(tài)或沒有運行笛谦,這些下載也會繼續(xù)抱虐。
- 可以暫停(取消)下載任務并稍后恢復它們(假設服務器支持這樣做);還可以恢復由于網絡連接問題而失敗的下載饥脑。
使用下載任務時恳邀,delegate
會收到幾個對下載場景唯一的回調
- 在下載期間,
URLSession
定期調用-URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
方法 - 下載完成后灶轰,
URLSession
調用-URLSession:downloadTask:didFinishDownloadingToURL:
方法谣沸; 在這個方法中,需要將臨時文件移動到應用程序的沙箱容器目錄中笋颤; - 下載失敗時乳附,
URLSession
調用-URLSession:task:didCompleteWithError:
方法獲取錯誤信息,例如無法解析主機名或無法連接到主機。
@interface NSURLSessionDownloadTask : NSURLSessionTask
/** 可以恢復下載的取消任務方法
* @param completionHandler 任務取消后的回調
* 如果允許取消的任務恢復下載许溅,在該回調中需要提供一個 resumeData;在恢復下載時秉版,系統(tǒng)將該 resumeData 傳遞給 NSURLSession 的 -downloadTaskWithResumeData: 或 -downloadTaskWithResumeData:completionHandler: 方法來創(chuàng)建一個新任務贤重,繼續(xù)它停止的地方的下載。
* 需要指定一個分派隊列清焕,以便在其中執(zhí)行Handler
*
* 什么情況下才能繼續(xù)下載該任務呢并蝗?
* <li> 自第一次 request,資源一直沒有更改
* <li> 任務是 HTTP 或 HTTPS GET 請求
* <li> 服務器在響應中提供 ETag 或 Last-Modified 頭(或兩者都提供)
* <li> 服務器支持 byte-range 請求
* <li> 系統(tǒng)沒有因為磁盤空間而刪除臨時文件
* 只有滿足上述條件秸妥,才能繼續(xù)下載該任務
*/
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;
@end
5滚停、StreamTask
從 iOS9 開始支持 NSURLSessionStreamTask
任務,這允許TCP/IP連接到指定的主機和可選的安全握手和代理導航的端口粥惧;使用 NSURLSession
顯示創(chuàng)建該任務键畴!
NSURLSessionStreamTask
是 NSURLSessionTask
的一個子類,在 NSURLSessionTask
基礎上增加了額外的功能突雪。
NSURLSessionStreamTask
在串行隊列中執(zhí)行異步讀寫操作起惕,讀寫操作完后或者失敗時在delegateQueue
上調用 completionHandler
。 調用 -captureStreams
方法創(chuàng)建 NSInputStream
和 NSOutputStream
實例咏删;所有未完成的讀寫在 streams
創(chuàng)建之前完成惹想。一旦 streams
被傳遞到 NSURLSessionStreamDelegate
的代理方法,任務就被認為完成督函,不再接收消息嘀粱;這些 streams
與 NSURLSession
分離。
5.1辰狡、讀寫數據
/** 異步地從 stream 中讀取字節(jié)锋叨,并在完成時調用 completionHandler
* @param minBytes 要讀取的最小字節(jié)數
* @param maxBytes 要讀取的最大字節(jié)數
* @param timeout 讀取字節(jié)的超時時間:如果在指定的時間間隔內未完成讀取,則取消讀取搓译,并調用 completionHandler 返回錯誤悲柱;
* 可以設置為 0 防止讀取超時;
* @param completionHandler 讀取完成或失敗時在 delegateQueue 上調用
* param data 從 stream 讀取的數據
* param atEOF 是否到達文件結束(EOF)些己,以便不能讀取更多數據
* param error 失敗的原因豌鸡;如果讀取成功則為nil
* @note 如果發(fā)生錯誤,任何未完成的讀取也將失敗段标,新的讀取請求將立即出錯涯冠。
*/
- (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * _Nullable data, BOOL atEOF, NSError * _Nullable error))completionHandler;
/** 異步地指定的數據底層 Socket,并在完成時調用 completionHandler
* @param data 待寫入的數據
* @param timeout 寫入字節(jié)的超時時間:如果在指定的時間間隔內未完成寫入逼庞,則取消寫入蛇更,并調用 completionHandler 返回錯誤;
* 可以設置為 0 防止寫入超時;
* @param completionHandler 寫入完成或失敗時在 delegateQueue 上調用
*
* @note completionHandler 的調用并不保證已經接收到所有字節(jié)派任,只能保證所有的數據都已寫入到內核
*/
- (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * _Nullable error))completionHandler;
5.2砸逊、捕捉 StreamData
/** 完成在串行隊列中等待的讀寫操作,然后調用 -URLSession:streamTask:didBecomeInputStream:outputStream: 代理方法掌逛。
* 在該代理方法中师逸,將認為任務已完成,不再接收任何代理消息豆混。
*/
- (void)captureStreams;
5.3篓像、關閉讀Socket、寫Socket
/** 完成隊列中的讀寫操作皿伺,然后關閉底層 Socket 的寫端
* 在調用此方法后员辩,可以繼續(xù)讀取數據 -readDataOfMinLength:maxLength:timeout:completionHandler: 直到流到達文件末尾(EOF)為止
* 但不能調用 -writeData:timeout:completionHandler: 否則發(fā)生錯誤。
*/
- (void)closeWrite;
/** 完成隊列中的讀寫操作鸵鸥,然后關閉底層 Socket 的讀端
* 調用此方法后奠滑,可以繼續(xù)寫入數據 -writeData:timeout:completionHandler:
* 但不能調用 -readDataOfMinLength:maxLength:timeout:completionHandler: 否則發(fā)生錯誤。
*/
- (void)closeRead;
5.4脂男、啟動和停止安全連接
/** 完成隊列中的的讀寫操作养叛,然后建立安全連接,加密 handshake
* TLS認證回調通過 -URLSession:task:didReceiveChallenge:completionHandler:
*/
- (void)startSecureConnection;
/** 隊列中的讀寫操作完成后宰翅,干凈地關閉安全連接弃甥。
* @warning 該方法已被廢棄
*/
- (void)stopSecureConnection API_DEPRECATED("TLS cannot be disabled once it is enabled", macos(10.9,10.15), ios(7.0,13.0), watchos(2.0,6.0), tvos(9.0,13.0));
6、WebSocket
任務
NSURLSessionWebSocketTask
是NSURLSessionTask
的子類汁讼,以 WebSocket
框架的形式在TCP和TLS上提供了面向消息的傳輸協議淆攻,它遵循RFC 6455中定義的WebSocket
協議。
一個 WebSocket
任務嘿架,客戶端也可以提供一個協議列表瓶珊,公布在WebSocket
握手階段;旦握手成功完成耸彪,通過一個可選的 delegate
被通知伞芹。在握手完成之前,客戶端可以被調用來處理 HTTP
重定向或身份認證蝉娜。
WebSocket
任務也支持 Cookie
唱较,將cookie存儲到 NSURLSession
的cookie中,并將cookie附加到傳出的 HTTP handshake 請求中召川。
6.1南缓、封裝的消息體
封裝的一個 WebSocket
消息,該對象將被傳遞給 -send
調用荧呐,并將從 -receive
調用中傳遞
/** 創(chuàng)建的消息類型:Data 或 String
*/
typedef NS_ENUM(NSInteger, NSURLSessionWebSocketMessageType) {
NSURLSessionWebSocketMessageTypeData = 0,
NSURLSessionWebSocketMessageTypeString = 1,
} API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0))
@interface NSURLSessionWebSocketMessage : NSObject
/** 使用 data 創(chuàng)建消息
* 此時屬性 string = nil
*/
- (instancetype)initWithData:(NSData *)data NS_DESIGNATED_INITIALIZER;
/** 使用 string 創(chuàng)建消息
* 此時屬性 data = nil
*/
- (instancetype)initWithString:(NSString *)string NS_DESIGNATED_INITIALIZER;
@property (readonly) NSURLSessionWebSocketMessageType type;
@property (nullable, readonly, copy) NSData *data;
@property (nullable, readonly, copy) NSString *string;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
6.2汉形、發(fā)送和接收數據
異步執(zhí)行讀寫操作纸镊,并允許發(fā)送和接收包含二進制幀和UTF-8編碼文本幀的消息;該任務會將握手完成前隊列中的讀寫操作將在握手成功后按順序執(zhí)行概疆;
/** 發(fā)送一個WebSocket消息
* @param message 待發(fā)送的WebSocket消息
* @param completionHandler 接收發(fā)送結果逗威,發(fā)送失敗返回 error ;發(fā)送成功則error=nil
* 如果出現錯誤岔冀,任何未完成的工作也將失斺挚;
* @note completionHandler的調用并不保證遠程端已經接收到所有字節(jié)楣颠,只是它們已經被寫入到內核。
*/
- (void)sendMessage:(NSURLSessionWebSocketMessage *)message completionHandler:(void (^)(NSError * _Nullable error))completionHandler;
/** 一旦消息的所有frames可用咐蚯,讀取一個WebSocket消息
* @param completionHandler 讀取結果童漩,成功獲取message,失敗返回 error春锋;
* @note 在緩沖frames時矫膨,如果達到了 maximumMessage ,則receiveMessage調用將出錯期奔,所有未完成的工作也將失敗侧馅,導致任務結束。
*/
- (void)receiveMessageWithCompletionHandler:(void (^)(NSURLSessionWebSocketMessage* _Nullable message, NSError * _Nullable error))completionHandler;
/** 在接收消息失敗之前緩沖的最大字節(jié)數
* 該值包括連續(xù)幀中所有字節(jié)的總和呐萌,一旦任務達到這個限制馁痴,receive 就會失敗。
*/
@property NSInteger maximumMessageSize;
/** 從客戶端發(fā)送一個ping幀肺孤,帶有一個從服務器端點接收pong的閉包罗晕。
* @param pongReceiveHandler 當客戶端收到來自服務器端點的pong時,該Block被調用赠堵;
* 如果在接收服務器端點pong之前連接丟失或發(fā)生錯誤小渊,該Block被調用返回錯誤信息
* 當發(fā)送多個ping時 ,pongReceiveHandler 將總是按照客戶端發(fā)送 ping 的順序被調用茫叭;
*
* @discussion Ping-pong 是一種數據傳輸技術酬屉,本質是一種數據緩沖的手段;同時利用客戶端揍愁、服務器兩個數據緩沖區(qū)達到數據連續(xù)傳輸的目的:
* 客戶端不必等待服務器的處理結果呐萨,繼續(xù)執(zhí)行并將結果保存在ping路的緩存中;客戶端執(zhí)行到一定時刻吗垮,服務端處理完成將結果 保存在pong路中垛吗;
* 這樣服務端模塊無需等待繼續(xù)執(zhí)行,客戶端也無需等待繼續(xù)執(zhí)行烁登,轉而將結果存儲在ping路怯屉;提高了處理效率蔚舀。
*
* 單個緩沖區(qū)得到的數據在傳輸和處理中很容易被覆蓋,而 Ping-pong 緩沖區(qū)的方式能夠總是保持一個緩沖區(qū)的數據被利用锨络,另一個緩沖去用于存儲數據赌躺;即兩個相同的對象作為緩沖區(qū)交替地被讀和 被寫。
*/
- (void)sendPingWithPongReceiveHandler:(void (^)(NSError* _Nullable error))pongReceiveHandler;
6.3羡儿、關閉連接
typedef NS_ENUM(NSInteger, NSURLSessionWebSocketCloseCode)
{
NSURLSessionWebSocketCloseCodeInvalid = 0,
NSURLSessionWebSocketCloseCodeNormalClosure = 1000,
NSURLSessionWebSocketCloseCodeGoingAway = 1001,
NSURLSessionWebSocketCloseCodeProtocolError = 1002,
NSURLSessionWebSocketCloseCodeUnsupportedData = 1003,
NSURLSessionWebSocketCloseCodeNoStatusReceived = 1005,
NSURLSessionWebSocketCloseCodeAbnormalClosure = 1006,
NSURLSessionWebSocketCloseCodeInvalidFramePayloadData = 1007,
NSURLSessionWebSocketCloseCodePolicyViolation = 1008,
NSURLSessionWebSocketCloseCodeMessageTooBig = 1009,
NSURLSessionWebSocketCloseCodeMandatoryExtensionMissing = 1010,
NSURLSessionWebSocketCloseCodeInternalServerError = 1011,
NSURLSessionWebSocketCloseCodeTLSHandshakeFailure = 1015,
} API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
/** 使用指定的 closeCode 發(fā)送一個關閉幀礼患,同時可以提供關閉的原因
* @param closeCode 關閉連接的原因
* @param reason 進一步解釋為何關閉,由客戶端自定義掠归,可傳 nil缅叠;
* @note 如果調用 [NSURLSessionTask cancel] 而非該方法,它會發(fā)送一個沒有closeCode或reason的關閉幀虏冻;
*/
- (void)cancelWithCloseCode:(NSURLSessionWebSocketCloseCode)closeCode reason:(NSData * _Nullable)reason;
/** 連接關閉原因仇让,可以在任何時候查看
* 當連接尚未關閉時呀闻,此值為 NSURLSessionWebSocketCloseCodeInvalid
*
* <ul> NSURLSessionWebSocketCloseCode : 說明 WebSocket 連接關閉的原因
* <li> NSURLSessionWebSocketCloseCodeInvalid 表示連接仍處于打開狀態(tài)
* <li> NSURLSessionWebSocketCloseCodeNormalClosure 表示連接正常關閉
* <li> NSURLSessionWebSocketCloseCodeGoingAway 表示服務器宕機或瀏覽器從頁面導航離開卫键,導致端點即將消失
* <li> NSURLSessionWebSocketCloseCodeProtocolError 表示端點由于協議錯誤而終止連接
* <li> NSURLSessionWebSocketCloseCodeUnsupportedData 表示端點接收到不能處理的數據類型后終止連接:如只接收文本的端點接收到二進制消息
* <li> NSURLSessionWebSocketCloseCodeNoStatusReceived 表示端點需要狀態(tài)碼而沒有接收到狀態(tài)碼
* <li> NSURLSessionWebSocketCloseCodeAbnormalClosure 表示連接在沒有關閉幀的情況下關閉
* <li> NSURLSessionWebSocketCloseCodeInvalidFramePayloadData 表示服務器接收到與消息類型不一致的數據而終止連接
* <li> NSURLSessionWebSocketCloseCodePolicyViolation 表示端點終止連接熬粗,因為它收到了違反其策略的消息
* <li> NSURLSessionWebSocketCloseCodeMessageTooBig 表示端點因接收到無法處理的大消息而終止連接
* <li> NSURLSessionWebSocketCloseCodeMandatoryExtensionMissing 表示客戶端終止連接,因為服務器沒有協商所需的擴展蛮穿;
* RFC 6455指示客戶端應該提供一個包含所需擴展的列表
* <li> NSURLSessionWebSocketCloseCodeInternalServerError 表示服務器因意外情況而終止連接
* <li> NSURLSessionWebSocketCloseCodeTLSHandshakeFailure 表示由于未能執(zhí)行TLS握手而關閉連接
* </ul>
*/
@property (readonly) NSURLSessionWebSocketCloseCode closeCode;
/** 連接關閉的詳細原因庶骄,可以在任何時候查看
* nil 表示沒有closeReason,也或許 SocketTask 仍在運行
*/
@property (nullable, readonly, copy) NSData *closeReason;