SocketRocket - facebook

socketRocket

WebSocket 协议

百度百科
http://www.tuicool.com/articles/7zyMvy6

HTML5一种新的协议,实现了浏览器与服务器全双工通信,一开始的握手需要借助HTTP请求完成;
传统的HTTP请求采用轮询,而HTTP的header是非常长的,这样会占用很多带宽;
WebSocket API中,浏览器只需要做一个握手的动作,然后,浏览器和服务器之间形成了一条快速通道,两者之间就直接可以数据互相传送;
HTTP的keep-alive是把多个http请求合并为一个,而Websocket是一个新协议;


Paste_Image.png

多出的 Upgrade,Connection字段表明是websocket请求;

  • 数据帧格式
    基本的数据帧为一个opcode、一个payload长度和发送的应用数据
    Paste_Image.png

1. 测试用例

2. 技术点

NSOperation

NSOperation 方法说明
(void)start; 启动 operation
isFinished, isExecuting 状态标识
在start函数里处理设计要执行的功能

  • 设计 operation
    设计一个基础的SRTWebSocketOperation<SRWebSocketDelegate>, 并代理处理SR webSocket的close及fail事件;
    SRAutobahnOperation : SRTWebSocketOperation 实际设计执行的子operation, 并处理delegate中消息接收的事件;
    设计了三个测试接口:
    SRAutobahnTestResultOperation 结果
    SRAutobahnTestCaseInfoOperation 信息
    SRAutobahnTestCaseCountOperation 数目
    SRAutobahnTestUpdateReportsOperation 更新
    每个接口创建对应的url测试

  • operation queue
    NSOperationQueue
    addDependency //依赖任务完成偶才开始执行其他任务
    addOperation

  • __bridge
    __bridge 关键字来实现id类型与void*类型的相互转换;
    __bridge_retained 是编译器替我们做了retain工作;
    __bridge_transfer 是编译器替我们做了release工作;

NSURL 使用

NSURLComponents
NSURLQueryItem

BLOCK

block copy ??? 使用copy有什么用途??//[textMessageHandler copy]
__block 定义变量,让block内部可改变

手动KVO

willChangeValueForKey / didChangeValueForKey 即时状态不变化也能触动observation?

DSP

DSP中的block使用self不会引起循环引用,使用weakSelf的是为了减少self的生命周期;因为block肯定会执行;

  • 使用 dispatch_group_t 同步
    diapatch_group_create / dispacth_group_enter / dispatch_group_wait / dispatch_group_leave
  • 使用 dispatch_semaphore_t 进行同步
  • dispatch_data_t
    某种程度上跟NSData类型相似;
    它的独特属性是它可以基于零碎的内存区域,对组合内存进行连接管理;
    dispatch_data_t c = dispatch_data_create_concat(a, b);
    它并不把数据copy到一个单独的更大的内存区域,相反的只是简单简单持有a和b对象;
    类似的,你可以使用dispatch_data_create_subrange来创建一个不做任何拷贝操作的子区域;
  • dispatch_benchmark
    测试代码执行的平均纳秒数,只在调试和性能分析上起作用;
编译相关

attribute ((vector_size (32))); 占32字节
_Alignof(type-name) 某类型的对齐要求

3. 结构设计

Paste_Image.png

4. 模块

Internal 模块

SRPinningSecurityPolicy : SRSecurityPolicy

使用 Security 框架

  • evaluateServerTrust
    遍历serverTrust对象,检查是否与pinnedCertificates中的某个证书一致,当验证所有pinned证书都正确时,返回YES,否则NO;
  • updateSecurityOptionsInStream
    设置NSStream对象的安全属性策略,支持TLS,是否支持证书链;
SRProxyConnect :NSObject

使用 NSStreamDelegate 代理,使用 CFNetwork 框架;
处理url的代理设置,有代理连接代理,无代理直接访问host;
属性:http与socket代理,SSL支持,输入数据数组

  • initWithURL:(NSURL *)url
    初始化工作,检查url是否需要SSL;
    创建写数据的 dispatch_queue,初始化输入数据数组
  • _configureProxy 取得系统代理并设置代理
    _fetchPAC 根据url自动发现代理,再调用_runPACScript取得代理设置
    _runPACScript 运行PAC的JS脚本取得代理设置
    _readProxySettingWithType 读取http或socket代理设置保存
  • _openConnection
    NSStream Foundation架构中定义
    _initializeStreams 根据url跟代理配置连接参数,调用CFStreamCreatePairWithSocketToHost 创建socket的read和write stream;
    NSInputStream / NSOutputStream open 打开stream;
  • (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;
    处理socket的read/write stream的代理事件,包括连接、错误、数据事件的处理;
    如果stream打开成功,检查是否有http代理,如果有发送http代理连接请求;
  • _didConnect
    表示根据代理设置已连接成功的处理,返回;
    设置input/outputStream为nil,取消代理,回调_completion;
  • _writeData
    这个数据只会是代理连接的请求数据;
    将数据写入到outStream中,并做错误与超时处理;
  • _processInputStream
    读取inputStream的数据放入到input队列中;
    CFHTTPMessageAppendBytes 将数据放入到代理头中,
    调用_proxyProcessHTTPResponseWithData检查代理是否连上了;
SRDelegateController :NSObject

设置DSP或者Operation来处理delegate的block;

IOConsumerPool :NSObject

存储管理poolSize个SRIOConsumer;

  • consumerWithScanner
    从pool中取出一个SRIOConsumer或者创建一个,并设置参数返回consumer;
  • returnConsumer
    向pool中添加一个consumer;
IOConsumer

管理io接口属性

  • resetWithScanner
    根据传入参数设置stream_scanner / data_callback函数指针,设置_bytesNeeded/_readToCurrentFrame/_unmaskBytes
SRRunLoopThread :NSThread 自定义线程类

通过自定义main 中 runloop来控制循环不退出,同时记录线程的 runloop

  • main 函数:添加一个空的 runloop source,并加入到 current runloop中,保持线程一直阻塞等待事件触发?

Utilities 模块

提供各种C接口工具函数

SRHash

对数据进行sha1或者base64编码
SHA1: Secure Hash Algorithm 安全哈希算法
Base64:网络上最常见的用于传输8Bit字节代码的编码方式之一,返回一个字符串;

SRHTTPConnectMessage

根据request,secureKey,协议版本,cookie及协议,来生成一个CFHTTPMessageRef的Http消息头;
CFHTTPMessageSetHeaderFieldValue:设置http消息头的字段,包括GET/Host/Cookie/Authorization/Connection/Sec-WebSocket-Key/Sec-WebSocket-Version/Sec-WebSocket-Protocol以及request中的key字段;

SRURLUtilities
  • SRURLRequiresSSL
    取得NSURL中的host,port,schema组织成一个 https://127.0.0.1:90像是的字符串;
  • SRURLRequiresSSL
    检查NSURL的schema中是否为wss还是https(表示SSL协议);
  • SRStreamNetworkServiceTypeFromURLRequest
    把NSURLRequest中的networkServiceType转换为NSStream类型的字符串;
    服务类型包括:默认正常、VoIP、Video、Background、Voice及Call Signaling;
SRSIMDHelpers

对数据进行SIMD的处理,使用多数据流能够加快数据处理

  • SIMD
    SIMD:Single Instruction Multiple Data 单指令多数据流,能够复制多个操作数,并把它们打包在大型寄存器的一组指令集;
    以加法指令为例,单指令单数据(SISD)的CPU对加法指令译码后,执行部件先访问内存,取得第一个操作数;之后再一次访问内存,取得第二个操作数;随后才能进行求和运算。而在SIMD型的CPU中,指令译码后几个执行部件同时访问内存,一次性获得所有操作数进行运算。这个特点使SIMD特别适合于多媒体应用等数据密集型运算;

Socket Rocket 模块

Paste_Image.png
SRWebSocket

主要连接接口及数据处理在这里面
SRWebSocketDelegate : handle status and message events
Constructor / open
属性:涉及NSURLRequest、SRSecurityPolicy、SRDelegateController、SRIOConsumer等对象;

  • (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates
    根据请求URL,协议,是否接受不信任的SSL证书,来创建请求;
    SRSecurityPolicy用来处理设置stream的安全策略;
    这个函数用于处初始化各个参数;
  • open
    超时处理、SRProxyConnect进行连接;
    在block中取得连接的 input/outputStream
    如果需要验证SSL,在接收到stream数据后对证书进行验证;
  • didConnect
    生成随机key,生成并发送webSocket的http连接请求消息;
    _pumpWriting 将数据写入到 _outputStream 发送出去;
  • sendString
    对数据进行frame组织并发送给webSocket服务端;参考webSocket协议;
    sendString --> _sendFrameWithOpcode --> SRMaskBytesSIMD + _writeData

10. 名词解释

PAC:代理自动配置,一个PAC文件包含一个JS形式的函数 “FindProxyForURL(url, host)” ;PAC文件中的URL可能是手工配置的,也可能是通过网页的网咯代理自发现协议(Web Proxy Autodiscovery Protocol)自动配置的;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,105评论 18 139
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,039评论 29 470
  • 史上最全的iOS面试题及答案 iOS面试小贴士———————————————回答好下面的足够了----------...
    Style_伟阅读 2,318评论 0 35
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 1,982评论 0 12
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,679评论 0 4