iOS系统SRWebSocket的源码解析下
四。 接着来讲讲数据的读和写:
当建立连接成功后,就会循环调用这么一个方法:
//读取http头部
- (void)_readHTTPHeader;
{
if (_receivedHTTPHeaders == NULL) {
//序列化的http消息
_receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO);
}
//不停的add consumer去读数据
[self _readUntilHeaderCompleteWithCallback:^(SRWebSocket *self, NSData *data) {
//拼接数据,拼到头部
CFHTTPMessageAppendBytes(_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length);
//判断是否接受完
if (CFHTTPMessageIsHeaderComplete(_receivedHTTPHeaders)) {
SRFastLog(@“Finished reading headers %@”, CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_receivedHTTPHeaders)));
[self _HTTPHeadersDidFinish];
} else {
//没读完递归调
[self _readHTTPHeader];
}
}];
}
记得楼主之前写过一篇即时通讯下数据粘包、断包处理实例(基于CocoaAsyncSocket),因此抛出一个问题,WebSocket需要处理数据的断包和粘包么?
答案是基本不需要。引用知乎上的一段回答:
RFC规范指出,WebSocket是一个message-based的协议,它可以自动将数据分片,并且自动将分片的数据组装。
也就是说,WebSocket的RFC标准是不会产生粘包、断包问题的。无需应用层开发人员关心缓存以及手工组装message。
然而理想与现实的不一致:RFC规范与实现的不一致,现实当中有几个问题:
每个message可以是一个或多个分片。message不记录长度,分片才记录长度。
message最大的长度可以达到 9,223,372,036,854,775,807 字节,是由于Payload的数据长度有63bit的限制。
很多WebSocket的实现其实并不按照标准的RFC实现完全,很多仅仅实现了50%就拿来用了。这就导致了,在WebSocket实现上的最大长度很难达到这个大小,于是,很多API的实现上是会有限制的,可能会限制你的发送的长度,也可能会把过长的数据直接以流式发送。
而SRWebSocket中实现的方式上彻底解决了数据粘包,断包的可能。
数据是通过CFStream流的方式回调回来的,每次拿到流数据,都是先放在数据缓冲区中,然后去读当前消息帧的头部,得到当前数据包的大小,然后再去创建消费者对象consumer,去读取缓冲区指定数据包大小的内容,读完才会回调给我们上层用户,所以,我们如果用SRWebSocket完全不需要考虑数据断包、粘包的问题,每次到达的数据,都是一条完整的数据。
接着我们大概来看看这个流程:
//读取CRLFCRLFBytes,直到回调回来
- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler;
{
[self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler];
}
//读取数据 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
//消费者需要消费的数据大小
stream_scanner consumer = ^size_t(NSData *data) {
__block size_t found_size = 0;
__block size_t match_count = 0;
//得到数据长度
size_t size = data.length;
//得到数据指针
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]) {
//匹配数+1
match_count += 1;
//如果匹配了
if (match_count == length) {
//读取数据长度等于 i+ 1
found_size = i + 1;
break;
}
} else {
match_count = 0;
}
}
//返回要读取数据的长度,没匹配成功就是0
return found_size;
非常好我支持^.^
(0) 0%
不好我反对
(0) 0%
下载地址
iOS系统SRWebSocket的源码解析下下载
相关电子资料下载
- iOS17.1可能明天发布,iOS17.1主要修复哪些问题? 377
- 华为全新鸿蒙蓄势待发 仅支持鸿蒙内核和鸿蒙系统应用 719
- 苹果手机系统iOS 17遭用户质疑 731
- iPhone12辐射超标?苹果推送iOS 17.1解决此事 750
- 传华为囤积零部件 目标明年智能手机出货7000万部;消息称 MiOS 仅限国内,小米 28208
- 苹果推送iOS17.0.3,解决iPhone15Pro系列存在机身过热 216
- Testin云测兼容和真机服务平台中上线iPhone 15系列手机 208
- 利尔达推出搭载HooRiiOS的Matter模组 145
- 运放参数解析:输入偏置电流(Ibias)和失调电流(Ios) 128
- 昆仑太科发布支持国产飞腾腾锐D2000芯片的开源BIOS固件版本 448