iOS系統(tǒng)SRWebSocket的源碼解析下
推薦 + 挑錯(cuò) + 收藏(0) + 用戶評(píng)論(0)
四。 接著來講講數(shù)據(jù)的讀和寫:
當(dāng)建立連接成功后,就會(huì)循環(huán)調(diào)用這么一個(gè)方法:
//讀取http頭部
- (void)_readHTTPHeader;
{
if (_receivedHTTPHeaders == NULL) {
//序列化的http消息
_receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO);
}
//不停的add consumer去讀數(shù)據(jù)
[self _readUntilHeaderCompleteWithCallback:^(SRWebSocket *self, NSData *data) {
//拼接數(shù)據(jù),拼到頭部
CFHTTPMessageAppendBytes(_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length);
//判斷是否接受完
if (CFHTTPMessageIsHeaderComplete(_receivedHTTPHeaders)) {
SRFastLog(@“Finished reading headers %@”, CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_receivedHTTPHeaders)));
?。踫elf _HTTPHeadersDidFinish];
} else {
//沒讀完遞歸調(diào)
?。踫elf _readHTTPHeader];
}
}];
}
記得樓主之前寫過一篇即時(shí)通訊下數(shù)據(jù)粘包、斷包處理實(shí)例(基于CocoaAsyncSocket),因此拋出一個(gè)問題,WebSocket需要處理數(shù)據(jù)的斷包和粘包么?
答案是基本不需要。引用知乎上的一段回答:
RFC規(guī)范指出,WebSocket是一個(gè)message-based的協(xié)議,它可以自動(dòng)將數(shù)據(jù)分片,并且自動(dòng)將分片的數(shù)據(jù)組裝。
也就是說,WebSocket的RFC標(biāo)準(zhǔn)是不會(huì)產(chǎn)生粘包、斷包問題的。無需應(yīng)用層開發(fā)人員關(guān)心緩存以及手工組裝message。
然而理想與現(xiàn)實(shí)的不一致:RFC規(guī)范與實(shí)現(xiàn)的不一致,現(xiàn)實(shí)當(dāng)中有幾個(gè)問題:
每個(gè)message可以是一個(gè)或多個(gè)分片。message不記錄長(zhǎng)度,分片才記錄長(zhǎng)度。
message最大的長(zhǎng)度可以達(dá)到 9,223,372,036,854,775,807 字節(jié),是由于Payload的數(shù)據(jù)長(zhǎng)度有63bit的限制。
很多WebSocket的實(shí)現(xiàn)其實(shí)并不按照標(biāo)準(zhǔn)的RFC實(shí)現(xiàn)完全,很多僅僅實(shí)現(xiàn)了50%就拿來用了。這就導(dǎo)致了,在WebSocket實(shí)現(xiàn)上的最大長(zhǎng)度很難達(dá)到這個(gè)大小,于是,很多API的實(shí)現(xiàn)上是會(huì)有限制的,可能會(huì)限制你的發(fā)送的長(zhǎng)度,也可能會(huì)把過長(zhǎng)的數(shù)據(jù)直接以流式發(fā)送。
而SRWebSocket中實(shí)現(xiàn)的方式上徹底解決了數(shù)據(jù)粘包,斷包的可能。
數(shù)據(jù)是通過CFStream流的方式回調(diào)回來的,每次拿到流數(shù)據(jù),都是先放在數(shù)據(jù)緩沖區(qū)中,然后去讀當(dāng)前消息幀的頭部,得到當(dāng)前數(shù)據(jù)包的大小,然后再去創(chuàng)建消費(fèi)者對(duì)象consumer,去讀取緩沖區(qū)指定數(shù)據(jù)包大小的內(nèi)容,讀完才會(huì)回調(diào)給我們上層用戶,所以,我們?nèi)绻肧RWebSocket完全不需要考慮數(shù)據(jù)斷包、粘包的問題,每次到達(dá)的數(shù)據(jù),都是一條完整的數(shù)據(jù)。
接著我們大概來看看這個(gè)流程:
//讀取CRLFCRLFBytes,直到回調(diào)回來
- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler;
{
[self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler];
}
//讀取數(shù)據(jù) CRLFCRLFBytes,邊界符
- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler;
{
// TODO optimize so this can continue from where we last searched
//消費(fèi)者需要消費(fèi)的數(shù)據(jù)大小
stream_scanner consumer = ^size_t(NSData *data) {
__block size_t found_size = 0;
__block size_t match_count = 0;
//得到數(shù)據(jù)長(zhǎng)度
size_t size = data.length;
//得到數(shù)據(jù)指針
const unsigned char *buffer = data.bytes;
for (size_t i = 0; i 《 size; i++ ) {
//匹配字符
if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) {
//匹配數(shù)+1
match_count += 1;
//如果匹配了
if (match_count == length) {
//讀取數(shù)據(jù)長(zhǎng)度等于 i+ 1
found_size = i + 1;
break;
}
} else {
match_count = 0;
}
}
//返回要讀取數(shù)據(jù)的長(zhǎng)度,沒匹配成功就是0
return found_size;
非常好我支持^.^
(0) 0%
不好我反對(duì)
(0) 0%
下載地址
iOS系統(tǒng)SRWebSocket的源碼解析下下載
相關(guān)電子資料下載
- iOS17.1可能明天發(fā)布,iOS17.1主要修復(fù)哪些問題? 377
- 華為全新鴻蒙蓄勢(shì)待發(fā) 僅支持鴻蒙內(nèi)核和鴻蒙系統(tǒng)應(yīng)用 719
- 蘋果手機(jī)系統(tǒng)iOS 17遭用戶質(zhì)疑 731
- iPhone12輻射超標(biāo)?蘋果推送iOS 17.1解決此事 750
- 傳華為囤積零部件 目標(biāo)明年智能手機(jī)出貨7000萬部;消息稱 MiOS 僅限國(guó)內(nèi),小米 28208
- 蘋果推送iOS17.0.3,解決iPhone15Pro系列存在機(jī)身過熱 216
- Testin云測(cè)兼容和真機(jī)服務(wù)平臺(tái)中上線iPhone 15系列手機(jī) 208
- 利爾達(dá)推出搭載HooRiiOS的Matter模組 145
- 運(yùn)放參數(shù)解析:輸入偏置電流(Ibias)和失調(diào)電流(Ios) 128
- 昆侖太科發(fā)布支持國(guó)產(chǎn)飛騰騰銳D2000芯片的開源BIOS固件版本 448